TinySpring学习(Step3)

来源:互联网 发布:shell脚本编程入门 编辑:程序博客网 时间:2024/06/05 07:57

step1、2中我们完成了一个简单的IOC的容器,可以利用反射将bean放入工厂。下边我们就看看step3做了什么

Step3 为bean注入属性

这一步,我们想要为bean注入属性。我们选择将属性注入信息保存成PropertyValue对象,并且保存到BeanDefinition中。这样在初始化bean的时候,我们就可以根据PropertyValue来进行bean属性的注入。Spring本身使用了setter来进行注入,这里为了代码简洁,我们使用Field的形式来注入。

类图(简单呈现,并不标准)

这里写图片描述

PropertyValue

public class PropertyValue {    private final String name;    private final Object value;    public PropertyValue(String name, Object value) {        this.name = name;        this.value = value;    }    public String getName() {        return name;    }    public Object getValue() {        return value;    }}

PropertyValues

public class PropertyValues {    private final List<PropertyValue> propertyValueList = new ArrayList<PropertyValue>();    public PropertyValues() {    }    public void addPropertyValue(PropertyValue pv) {        //TODO:这里可以对于重复propertyName进行判断,直接用list没法做到        this.propertyValueList.add(pv);    }    public List<PropertyValue> getPropertyValues() {        return this.propertyValueList;    }}

BeanDefinition

public class BeanDefinition {    ...//相同的部分不再重复    private PropertyValues propertyValues;    public PropertyValues getPropertyValues() {        return propertyValues;    }    public void setPropertyValues(PropertyValues propertyValues) {        this.propertyValues = propertyValues;    }}

AutowireCapableBeanFactory

@Override    protected Object doCreateBean(BeanDefinition beanDefinition) throws Exception {        Object bean = createBeanInstance(beanDefinition);        applyPropertyValues(bean, beanDefinition);        return bean;    }    protected Object createBeanInstance(BeanDefinition beanDefinition) throws Exception {        return beanDefinition.getBeanClass().newInstance();    }    protected void applyPropertyValues(Object bean, BeanDefinition mbd) throws Exception {        for (PropertyValue propertyValue : mbd.getPropertyValues().getPropertyValues()) {            Field declaredField = bean.getClass().getDeclaredField(propertyValue.getName());            declaredField.setAccessible(true);            declaredField.set(bean, propertyValue.getValue());        }    }

测试类:

public class HelloWorldService {    private String text;    public void helloWorld(){        System.out.println(text);    }    public void setText(String text) {        this.text = text;    }}
@Test    public void test() throws Exception {        // 1.初始化beanfactory        BeanFactory beanFactory = new AutowireCapableBeanFactory();        // 2.bean定义        BeanDefinition beanDefinition = new BeanDefinition();        beanDefinition.setBeanClassName("us.codecraft.tinyioc.HelloWorldService");        // 3.设置属性        PropertyValues propertyValues = new PropertyValues();        propertyValues.addPropertyValue(new PropertyValue("text", "Hello World!"));        beanDefinition.setPropertyValues(propertyValues);        // 4.生成bean        beanFactory.registerBeanDefinition("helloWorldService", beanDefinition);        // 5.获取bean        HelloWorldService helloWorldService = (HelloWorldService) beanFactory.getBean("helloWorldService");        helloWorldService.helloWorld();    }

走测试方法前3步的过程就是在装配beanDefinition的过程,下图就是走完前3步代码呈现的结果,我们可以发现,在第二步的时候得到了beanClass,也就是说通过类名,我们找到了这个具体的类,第3步就是然后往类(beanDefinition)里边set属性:

这里写图片描述

接下来就是生成bean的过程:
1. doCreateBean:传入的参数是上一步装配好的beanDefinition对象,这一步主要是实例化我们的HelloWorldService对象,然后给我们的对象附上属性值

上述过程被作者拆分成了三个方法,这也是我们在代码中需要学习的地方,一个方法只做一件事,作者的第一个方法是doCreateBean,这个方法调用了其他两个方法,第二个方法是createBeanInstance实例化类的对象,第三个方法是给类的字段赋值applyPropertyValues,这样看代码就非常的清晰且明了,一目了然,这三个方法可以说是生成bean的核心代码,都利用了反射的机制来实现

最后,bean就被生成出来了,跟第二个过程相比,只是加入了属性的赋值,架构上边没有大的调整,下一篇,我们将学习通过配置文件进行bean的生成

原创粉丝点击