Spring 框架源码解读5

作者: 想54256 | 来源:发表于2020-04-16 20:38 被阅读0次

    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

    嵌套的太深,不想看

    相关文章

      网友评论

        本文标题:Spring 框架源码解读5

        本文链接:https://www.haomeiwen.com/subject/awtjvhtx.html