美文网首页
Spring 源码深入理解 1

Spring 源码深入理解 1

作者: 学习吧朱小宁 | 来源:发表于2019-11-28 20:08 被阅读0次

    简版Spring 学习
    spring源码直接上手阅读较为困难,发现了一个简版的Spring,根据step1--step10,看着作者是一步步把spring整个框架搭起来的,一步步顺着spring的功能完善代码,顺便学学spring类的组织结构

    https://github.com/code4craft/tiny-spring/releases

    step 1 :

    Spring中bean的管理对象为一个Map

    private Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>();
    
    

    BeanDefinition 仅为一个Object类存在 不做其他处理 够简单。。。

    使用工厂模式进行创建统一的实体并保存至 ConcurrentHashMap 中

    public void registerBeanDefinition(String name, BeanDefinition beanDefinition) {
            beanDefinitionMap.put(name, beanDefinition);
            System.out.println(name + " 注册成功 ");
    }
    

    在调用时候 , 应首先初始化 工厂 (BeanFactory) , 得到BeanDefinition , 调用registerBeanDefinition 进行统一管理

    1574735573903.png

    step2

    代码结构

    代码结构 1574766317885.png

    此次BeanDefinition 增加了属性 bean对象 、 bean类对象 、 bean类对象名称。 在该对象设置类对象名称时,同步将类对象进行记录。setBeanClassName(beanClassName)

        private Object bean;
        private Class beanClass;
        private String beanClassName;
        
        public BeanDefinition() {
        }
        
        //主要方法
        public void setBeanClassName(String beanClassName) {
            this.beanClassName = beanClassName;
            try {
                this.beanClass = Class.forName(beanClassName);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
    

    使用抽象工厂模式,注册方法不变,更新增加了 初始化bean方法 doCreateBean() 根据类对象创建实例

    protected abstract Object doCreateBean(BeanDefinition beanDefinition);
    
        @Override
        protected Object doCreateBean(BeanDefinition beanDefinition) {
            try {
                Object bean = beanDefinition.getBeanClass().newInstance();
                return bean;
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            return null;
        }
    
        @Override
        public void registerBeanDefinition(String name, BeanDefinition beanDefinition) {
            Object bean = doCreateBean(beanDefinition);
            beanDefinition.setBean(bean);
            beanDefinitionMap.put(name, beanDefinition);
        }
    

    在工厂模式进行注册时候,只需要进行创建对应的Bean对象,然后放入Map中进行管理。

    调用顺序为

    setBeanClassName(); // 创建bean相关对象 存储类对象名称 然后setter方法会自动构造类对象
        registerBeanDefinition(); // 调用工厂注册进map
            doCreateBean(); // 首先根据类对象进行new实例
                beanDefinitionMap.put(name, beanDefinition); // 存入map
    
    1574766317885.png

    step3

    此项目在原有基础上BeanDefinition增加了PropertyValues属性(List<PropertyValue>)。

    public class BeanDefinition {
    
        private Object bean;
    
        private Class beanClass;
    
        private String beanClassName;
        //新增属性
        private PropertyValues propertyValues;
    }
    //模拟对象所有属性值集合
    public class PropertyValues {
    
        private final List<PropertyValue> propertyValueList = new ArrayList<PropertyValue>();
        
            public void addPropertyValue(PropertyValue pv) {
            //TODO:这里可以对于重复propertyName进行判断,直接用list没法做到
            this.propertyValueList.add(pv);
        }
    }
    
    //模拟对象属性
    public class PropertyValue {
    
        private final String name;
    
        private final Object value;
    }
    
    

    新增属性字段,则在其创建对象过程中应当为对象进行赋值。上个版本提到过 doCreateBean()为创建对象实例的接口,则应该在其创建对象完毕之后,注入属性。根据类对象及其属性名称、属性值进行对象属性赋值,使用 反射进行操作。 反射需要设置setAccessible(true) 否则不能正常找到对应其私有变量。

    @Override
        protected Object doCreateBean(BeanDefinition beanDefinition) throws Exception {
            Object bean = createBeanInstance(beanDefinition);
            applyPropertyValues(bean, beanDefinition);
            return bean;
        }
        
        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());
            }
        }
    
    

    所以此次测试,依然为传入类对象全路径名称,设置PropertyValues集合,使用beanFactory 进行注册托管,最后使用托管map 实例进行访问方法。


    1574942309712.png

    相关文章

      网友评论

          本文标题:Spring 源码深入理解 1

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