Spring 源码深入理解 1

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

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

step 1 :

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

private Map beanDefinitionMap = new ConcurrentHashMap();

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)。

public class BeanDefinition {

    private Object bean;

    private Class beanClass;

    private String beanClassName;
    //新增属性
    private PropertyValues propertyValues;
}
//模拟对象所有属性值集合
public class PropertyValues {

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