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
嵌套的太深,不想看