什么是属性填充
属性填充可以在类 AbstractAutowireCapableBeanFactory 的 createBean 方法中添加补全属性方法。
1.属性填充要在类实例化创建之后,也就是需要在 AbstractAutowireCapableBeanFactory 的 createBean 方法中添加 applyPropertyValues 操作。由于我们需要在创建Bean时候填充属性操作,那么就需要在 bean 定义 BeanDefinition 类中,添加 PropertyValues 信息。
2.填充属性信息还包括了 Bean 的对象类型(当前bean对其他bean的引用),也就是需要再定义一个 BeanReference,里面其实就是一个简单的 Bean 名称,在具体的实例化操作时进行递归创建和填充。这一步也称为bean注入bean 暂时不考虑循环依赖问题
定义PropertyValue类->该类是一个bean属性的格式
public class PropertyValue {
private final String name;
private final Object value;
public PropertyValue(String name, Object value) {
this.name = name;
this.value = value;
}
public String getName() {
return name;
}
public Object getValue() {
return value;
}
}
该类是bean属性信息的集合
package org.springframework.beans;
import java.util.ArrayList;
import java.util.List;
/**
* @author mwan
*/
public class PropertyValues {
//获取列表
private final List<PropertyValue> propertyValueList = new ArrayList<>();
//添加属性
public void addPropertyValue(PropertyValue pv) {
propertyValueList.add(pv);
}
//这行代码什么含义??
public PropertyValue[] getPropertyValues() {
return this.propertyValueList.toArray(new PropertyValue[0]);
}
//获取某个属性
public PropertyValue getPropertyValue(String propertyName) {
for (int i = 0; i < this.propertyValueList.size(); i++) {
PropertyValue pv = this.propertyValueList.get(i);
if (pv.getName().equals(propertyName)) {
return pv;
}
}
return null;
}
}
bean定义信息补全
/**
* BeanDefinition实例保存bean的信息,包括class类型、方法构造参数、bean属性、bean的scope等,此处简化只包含class类型和bean属性
*
* @author mwan
*/
public class BeanDefinition {
private Class beanClass;
private PropertyValues propertyValues;
public BeanDefinition(Class beanClass) {
this(beanClass, null);
}
public BeanDefinition(Class beanClass, PropertyValues propertyValues) {
this.beanClass = beanClass;
this.propertyValues = propertyValues != null ? propertyValues : new PropertyValues();
}
public Class getBeanClass() {
return beanClass;
}
public void setBeanClass(Class beanClass) {
this.beanClass = beanClass;
}
public PropertyValues getPropertyValues() {
return propertyValues;
}
public void setPropertyValues(PropertyValues propertyValues) {
this.propertyValues = propertyValues;
}
}
主要作用是bean的属性填充
主要关注 createBean 的方法中调用的 applyPropertyValues 方法。
在 applyPropertyValues 中,通过获取 beanDefinition.getPropertyValues() 循环进行属性填充操作,如果遇到的是 BeanReference,那么就需要递归获取 Bean 实例,调用 getBean 方法。
/**
* @author mwan
*/
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory {
private InstantiationStrategy instantiationStrategy = new SimpleInstantiationStrategy();
@Override
protected Object createBean(String beanName, BeanDefinition beanDefinition) throws BeansException {
return doCreateBean(beanName, beanDefinition);
}
protected Object doCreateBean(String beanName, BeanDefinition beanDefinition) {
Object bean = null;
try {
bean = createBeanInstance(beanDefinition);
//为bean填充属性
applyPropertyValues(beanName, bean, beanDefinition);
} catch (Exception e) {
throw new BeansException("Instantiation of bean failed", e);
}
addSingleton(beanName, bean);
return bean;
}
/**
* 实例化bean
*
* @param beanDefinition
* @return
*/
protected Object createBeanInstance(BeanDefinition beanDefinition) {
return getInstantiationStrategy().instantiate(beanDefinition);
}
/**
* 为bean填充属性
*
* @param bean
* @param beanDefinition
*/
protected void applyPropertyValues(String beanName, Object bean, BeanDefinition beanDefinition) {
try {
for (PropertyValue propertyValue : beanDefinition.getPropertyValues().getPropertyValues()) {
String name = propertyValue.getName();
Object value = propertyValue.getValue();
if (value instanceof BeanReference) {
// beanA依赖beanB,先实例化beanB
BeanReference beanReference = (BeanReference) value;
//getBean递归调用 会先create beanB 为其赋值并实例化
value = getBean(beanReference.getBeanName());
}
//通过反射设置属性
BeanUtil.setFieldValue(bean, name, value);
}
} catch (Exception ex) {
throw new BeansException("Error setting property values for bean: " + beanName, ex);
}
}
public InstantiationStrategy getInstantiationStrategy() {
return instantiationStrategy;
}
public void setInstantiationStrategy(InstantiationStrategy instantiationStrategy) {
this.instantiationStrategy = instantiationStrategy;
}
}