bean属性填充的设计
什么是属性填充
属性填充可以在类 AbstractAutowireCapableBeanFactory 的 createBean 方法中添加补全属性方法。
属性填充要做的事情
1.属性填充要在类实例化创建之后,也就是需要在 AbstractAutowireCapableBeanFactory 的 createBean 方法中添加 applyPropertyValues 操作。由于我们需要在创建Bean时候填充属性操作,那么就需要在 bean 定义 BeanDefinition 类中,添加 PropertyValues 信息。
2.填充属性信息还包括了 Bean 的对象类型(当前bean对其他bean的引用),也就是需要再定义一个 BeanReference,里面其实就是一个简单的 Bean 名称,在具体的实例化操作时进行递归创建和填充。这一步也称为bean注入bean 暂时不考虑循环依赖问题
相关代码
PropertyValue
定义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; } }
PropertyValues
该类是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; } }
BeanDefinition
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; } }
AbstractAutowireCapableBeanFactory
主要作用是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; } }