简版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.pngstep2
代码结构
代码结构 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
网友评论