程序员社区

Spring 框架源码解读5


title: Spring 框架源码解读5
date: 2020/04/16 20:32


本节内容 & 思考题

带大家实现依赖注入部分

DI

1、BD 增加属性

// 属性参数列表
private List<PropertyArgDefinition> properties;

public class PropertyArgDefinition {

    /**
     * 属性名称
     */
    private String name;

    /**
     * 类型
     */
    private String type;

    /**
     * 参数值
     */
    private String value;

    /**
     * 引用名称
     */
    private String refName;

2、新增 PropertyValue

public class PropertyValue {

    /**
     * Property name
     */
    private String name;

    /**
     * Value of the property
     */
    private Object value;

3、新增 BeanWrapper,封装一些注入属性的方法

/**
 * 对 bean 进行包装,封装一些注入属性的方法
 *
 * @author yujx
 * @date 2020/04/16 17:29
 */
public class BeanWrapper {

    private Object bean;

    public BeanWrapper(Object bean) {
        this.bean = bean;
    }

    public void setPropertyValue(PropertyValue pv) {

        // 字段名
        String name = pv.getName();

        // 值
        Object value = pv.getValue();

        // 设置值
        ReflectUtil.setFieldValue(bean, name, value);
    }

    public void setPropertyValues(List<PropertyValue> pvs) {
        for (PropertyValue pv : pvs) {
            this.setPropertyValue(pv);
        }
    }

    public Object getWrappedInstance() {
        return bean;
    }
}

4、修改 AbstractBF

public abstract class AbstractBeanFactory implements BeanFactory {

    ...

    /**
     * 根据 bd 创建对象
     * <p>
     * 1)创建bean 日后需要对有参构造进行扩展
     * 2)注入属性  日后新增
     * 3)执行初始化操作
     * 4)注册销毁的处理
     */
    private Object createBean(BeanDefinition beanDefinition) {

        // 1、创建 bean
        BeanWrapper beanWrapper = this.createBeanInstance(beanDefinition);

        // 2、注入属性 DI (Spring 0.9 中当属性改变时会触发事件,但是默认是关闭的,暂时不知道它为了干啥)
        List<PropertyArgDefinition> properties = beanDefinition.getProperties();
        List<PropertyValue> propertyValueList = this.parseProperties(properties);
        beanWrapper.setPropertyValues(propertyValueList);
        Object bean = beanWrapper.getWrappedInstance();

        // 3、执行初始化操作(在 Spring 中是直接调用的该类中的 initializeBean 方法,为了让他面向对象一点,我给他抽出一个类)
        InitializeBeanAdapter initializeBeanAdapter = new InitializeBeanAdapter(bean, beanDefinition);
        initializeBeanAdapter.afterPropertiesSet();

        // 4、注册销毁的处理
        if (this.check(beanDefinition, bean)) {
            registry.registerDisposableBean(beanDefinition.getName(), new DisposableBeanAdapter(bean, beanDefinition));
        }

        return bean;
    }

    private List<PropertyValue> parseProperties(List<PropertyArgDefinition> properties) {

        if (CollectionUtil.isEmpty(properties)) {
            return Collections.emptyList();
        }

        List<PropertyValue> propertyValueList = new ArrayList<>(properties.size());

        for (PropertyArgDefinition property : properties) {
            String propertyName = property.getName();
            String refBeanName = property.getRefName();
            if (ObjectUtil.isNotNull(refBeanName)) {
                Object refBean = this.getBean(refBeanName);
                PropertyValue propertyValue = new PropertyValue(propertyName, refBean);
                propertyValueList.add(propertyValue);
            } else {
                String value = property.getValue();
                try {
                    Class<?> clazz = Class.forName(property.getType());
                    PropertyValue propertyValue = new PropertyValue(propertyName, ReflectUtils.string2BasicType(value, clazz));
                    propertyValueList.add(propertyValue);
                } catch (ClassNotFoundException e) {
                    throw new RuntimeException(e);
                }
            }
        }

        return propertyValueList;
    }

5、测试

public class TestJsonBF {
    public static void main(String[] args) {
        ListableBeanFactory bf = new JsonBeanFactoryImpl("/Users/x5456/IdeaProjects/Summer/src/test/resources/apple.json");
        Grape grape = bf.getBean("grape", Grape.class);
        System.out.println(grape);
    }
}

public class Grape {

    private String name;

    private Apple apple;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Apple getApple() {
        return apple;
    }

    public void setApple(Apple apple) {
        this.apple = apple;
    }

    @Override
    public String toString() {
        return "Grape{" +
                "name='" + name + '\'' +
                ", apple=" + apple +
                '}';
    }
}

apple.json

[
  {
    "name": "appleFactory",
    "className": "cn.x5456.summer.AppleFactory"
  },
  {
    "name": "apple",
    "factoryBean": "appleFactory",
    "factoryMethod": "createApple"
  },
  {
    "name": "grape",
    "className": "cn.x5456.summer.Grape",
    "properties": [
      {
        "name": "name",
        "type": "java.lang.String",
        "value": "黑珍珠"
      },{
        "name": "apple",
        "refName": "apple"
      }
    ]
  }
]

Spring 0.9

实现大体相同,在属性修改的时候会触发事件,但是默认是关闭的,暂时不知道它为了干啥

Spring 5.0

嵌套的太深,不想看

赞(0) 打赏
未经允许不得转载:IDEA激活码 » Spring 框架源码解读5

一个分享Java & Python知识的社区