TinySpring学习(Step3)

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

Step3 为bean注入属性

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

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

TinySpring学习(Step3)_第1张图片

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 propertyValueList = new ArrayList();

    public PropertyValues() {
    }

    public void addPropertyValue(PropertyValue pv) {
        //TODO:这里可以对于重复propertyName进行判断,直接用list没法做到
        this.propertyValueList.add(pv);
    }

    public List 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属性:

TinySpring学习(Step3)_第2张图片

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

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

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

你可能感兴趣的:(♥,框架知识,-----,【Spring】,Spring学习记录)