使用属性值填充给定 BeanWrapper 中的 bean 实例。
概要流程图
@SuppressWarnings("deprecation") // for postProcessPropertyValuesprotected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {// 包装类为空if (bw == null) {// 如果有属性的话,但是没处理就抛出异常了if (mbd.hasPropertyValues()) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");} else {// Skip property population phase for null instance.return;}}// 让后扩展处理器加入// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the// state of the bean before properties are set. This can be used, for example,// to support styles of field injection.if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {return;}}}}// 获取属性PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);// 获取属性的注入类型int resolvedAutowireMode = mbd.getResolvedAutowireMode();if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {// 通过名称或者类型注入MutablePropertyValues newPvs = new MutablePropertyValues(pvs);// Add property values based on autowire by name if applicable.if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {autowireByName(beanName, mbd, bw, newPvs);}// Add property values based on autowire by type if applicable.if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {autowireByType(beanName, mbd, bw, newPvs);}pvs = newPvs;}boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);PropertyDescriptor[] filteredPds = null;if (hasInstAwareBpps) {if (pvs == null) {pvs = mbd.getPropertyValues();}for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);if (pvsToUse == null) {if (filteredPds == null) {filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);}pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);if (pvsToUse == null) {return;}}pvs = pvsToUse;}}}if (needsDepCheck) {if (filteredPds == null) {filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);}checkDependencies(beanName, mbd, filteredPds, pvs);}if (pvs != null) {applyPropertyValues(beanName, mbd, bw, pvs);}}
流程1 - 参数校验
// 包装类为空if (bw == null) {// 如果有属性的话,但是没处理就抛出异常了if (mbd.hasPropertyValues()) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");} else {// Skip property population phase for null instance.return;}}
流程2 - 后扩展加入
通过 InstantiationAwareBeanPostProcessor 扩展点,这里是实例化后,填充属性前用户可以调整bean的机会。它可以决定是否执行后面的填充逻辑。
// 让后扩展处理器加入// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the// state of the bean before properties are set. This can be used, for example,// to support styles of field injection.if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {return;}}}}
代码演示
准备bean
public class Dog {private String name;private Integer age;public Dog() {System.out.println("Dog init!!");}public Dog(String name, Integer age) {System.out.println("Dog init!!");this.name = name;this.age = age;}public void say(){System.out.println("wwwwwwwww");}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}}
增加自定义扩展,这里我们修改bean的属性name。
public class OrgInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {@Overridepublic boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {if (bean.getClass() == Dog.class) {Dog dog = (Dog) bean;dog.setName("哈哈哈哈哈");}return false;}}
bean 加入 IOC
<?xml version="1.0" encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsd"><bean id="dog" class="cn.lichenghao.entity.Dog"><property name="name" value="d1"/><property name="age" value="12"/></bean><bean id="orgInstantiationAwareBeanPostProcessor"class="cn.lichenghao.processor.OrgInstantiationAwareBeanPostProcessor"/></beans>
测试
可以看出,我们定义的 bean 被我们的自定义扩展修改 name 值后结束。
@DisplayName("自定义InstantiationAwareBeanPostProcessor")@Testpublic void OrgInstantiationAwareBeanPostProcessor() {ClassPathXmlApplicationContext classPathXmlApplicationContext= new ClassPathXmlApplicationContext("processor/InstantiationAwareBeanPostProcessor.xml");Dog dog = classPathXmlApplicationContext.getBean(Dog.class);System.out.println(dog.getName());}// 结果Dog init!!哈哈哈哈哈
流程3 - 解析属性
AutowireCapableBeanFactory 接口中定义了各种注入类型如下所示:
| resolvedAutowireMode | 依赖注入方式 | 描述 |
|---|---|---|
| 0 | AUTOWIRE_NO | 没有显式配置上装配的方式(默认) |
| 1 | AUTOWIRE_BY_NAME | 按 beanName 进行装配 |
| 2 | AUTOWIRE_BY_TYPE | 按 type 进行装配 |
| 3 | AUTOWIRE_CONSTRUCTOR | 在构造函数中进行装配 |
| 4 | AUTOWIRE_AUTODETECT | @Deprecated |
// 获取属性PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);// 获取属性的注入类型,默认情况下为0int resolvedAutowireMode = mbd.getResolvedAutowireMode();if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {// 通过名称或者类型注入MutablePropertyValues newPvs = new MutablePropertyValues(pvs);// Add property values based on autowire by name if applicable.// 通过名称注入if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {autowireByName(beanName, mbd, bw, newPvs);}// Add property values based on autowire by type if applicable.// 通过类型注入if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {autowireByType(beanName, mbd, bw, newPvs);}pvs = newPvs;}
当在配置文件中指定了注入类型才会进入这个分支。
比如:
根据名称获取属性 autowireByName
protected void autowireByName(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {// 过滤得到需要根据名称注入的属性String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);for (String propertyName : propertyNames) {// 判断依赖的属性是否有指定的beanif (containsBean(propertyName)) {// 得到依赖的beanObject bean = getBean(propertyName);// 加入pvspvs.add(propertyName, bean);// 加入缓存registerDependentBean(propertyName, beanName);if (logger.isTraceEnabled()) {logger.trace("Added autowiring by name from bean name '" + beanName +"' via property '" + propertyName + "' to bean named '" + propertyName + "'");}} else {if (logger.isTraceEnabled()) {logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +"' by name: no matching bean found");}}}}
过程:
- 首先通过方法 unsatisfiedNonSimpleProperties 过滤得到属性;
遍历这些属性,判断是否为注册的 bean,进而得到该 bean,加入到 MutablePropertyValues,并加入到缓存中(便于销毁)。
unsatisfiedNonSimpleProperties
过滤得到需要填充的属性,那么得到哪些属性?
属性有 set 方法;
- 属性不是被排除的;
- 不是当前对象的属性;
- 属性类型不是简单的类型比如:String,Number 子类 或者 简单类型的数组。
所以得到的是引用类型的属性。
protected String[] unsatisfiedNonSimpleProperties(AbstractBeanDefinition mbd, BeanWrapper bw) {Set<String> result = new TreeSet<>();PropertyValues pvs = mbd.getPropertyValues();// PropertyDescriptor:java.beans提供,获取当前Bean的类里面具体的属性和其getter, setter方法PropertyDescriptor[] pds = bw.getPropertyDescriptors();for (PropertyDescriptor pd : pds) {// pd.getWriteMethod() != null :属性有set方法// !isExcludedFromDependencyCheck(pd) :属性不是从依赖项检查中排除的// !pvs.contains(pd.getName()) :pvs中不包含// !BeanUtils.isSimpleProperty(pd.getPropertyType()) :不是简单的类型比如:String,Number子类等等if (pd.getWriteMethod() != null&& !isExcludedFromDependencyCheck(pd)&& !pvs.contains(pd.getName())&& !BeanUtils.isSimpleProperty(pd.getPropertyType())) {result.add(pd.getName());}}return StringUtils.toStringArray(result);}
registerDependentBean
将属性依赖的 bean 加入缓存中。为了以后统一销毁用。
这涉及到两个缓存:dependentBeans,dependenciesForBeanMap。
假设:有bean:a、b、c、d 都包含属性 bean:dog (a,b,c,d,dog 是 bean 的 name)
dependentBeans:dog-{a,b,c,d}
dependenciesForBeanMap: a-{dog}, b-{dog},c-{dog}, d-{dog},
源码如下:
public void registerDependentBean(String beanName, String dependentBeanName) {/*** 缓存。比如Bean: a,b,c,d 都有属性Bean: dog** dependentBeanMap : dog-[a,b,c,d]* dependenciesForBeanMap:a-[dog,cat],b-[dog]*/String canonicalName = canonicalName(beanName);synchronized (this.dependentBeanMap) {Set<String> dependentBeans =this.dependentBeanMap.computeIfAbsent(canonicalName, k -> new LinkedHashSet<>(8));if (!dependentBeans.add(dependentBeanName)) {return;}}synchronized (this.dependenciesForBeanMap) {Set<String> dependenciesForBean =this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, k -> new LinkedHashSet<>(8));dependenciesForBean.add(canonicalName);}}
打码测试
准备bean
public class Dog {private String name;private Integer age;public Dog() {System.out.println("Dog init!!");}public Dog(String name, Integer age) {System.out.println("Dog init!!");this.name = name;this.age = age;}public void say() {System.out.println("wwwwwwwww");}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}}
测试bean依赖上面的bean
public class AutowireByNameService {private Dog dog;public void setDog(Dog dog) {this.dog = dog;}public void doSomething() {dog.say();}}
加入容器
<?xml version="1.0" encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsd"><bean id="dog" class="cn.lichenghao.populateBean.entity.Dog"><property name="name" value="Tom"/><property name="age" value="12"/></bean><bean id="autowireByNameService"class="cn.lichenghao.populateBean.service.AutowireByNameService" autowire="byName"/></beans>
测试
@DisplayName("测试根据属性名称注入")@Testpublic void autowireByNameServiceTest() {ClassPathXmlApplicationContext classPathXmlApplicationContext= new ClassPathXmlApplicationContext("populateBean/s1.xml");AutowireByNameService bean = classPathXmlApplicationContext.getBean(AutowireByNameService.class);bean.doSomething();}
默认情况下,依赖bean的名称首字母小写去匹配。如果把 xml 中的配置的 id 修改为其他值,那么就会找不到了。
根据类型获取属性 autowireByType
protected void autowireByType(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {TypeConverter converter = getCustomTypeConverter();if (converter == null) {converter = bw;}Set<String> autowiredBeanNames = new LinkedHashSet<>(4);String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);for (String propertyName : propertyNames) {try {PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);// Don't try autowiring by type for type Object: never makes sense,// even if it technically is a unsatisfied, non-simple property.if (Object.class != pd.getPropertyType()) {MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);// Do not allow eager init for type matching in case of a prioritized post-processor.boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered);DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);Object autowiredArgument= resolveDependency(desc, beanName, autowiredBeanNames, converter);if (autowiredArgument != null) {pvs.add(propertyName, autowiredArgument);}for (String autowiredBeanName : autowiredBeanNames) {registerDependentBean(autowiredBeanName, beanName);if (logger.isTraceEnabled()) {logger.trace("Autowiring by type from bean name '"+ beanName + "' via property '"+ propertyName + "' to bean named '" + autowiredBeanName + "'");}}autowiredBeanNames.clear();}} catch (BeansException ex) {throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);}}}
同样首先过滤得到需要填充的属性;
流程4 - 解析注解相关处理器
后处理器,主要用来处理一些注解注入,如:
AutowiredAnnotationBeanPostProcessor 用于处理 @Autowired 和 @Value 注解;
CommonAnnotationBeanPostProcessor 用于处理 @Resource 注解。
// 是否有后处理器boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();// 依赖检查boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);PropertyDescriptor[] filteredPds = null;if (hasInstAwareBpps) {if (pvs == null) {pvs = mbd.getPropertyValues();}for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);if (pvsToUse == null) {if (filteredPds == null) {filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);}pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);if (pvsToUse == null) {return;}}pvs = pvsToUse;}}}if (needsDepCheck) {if (filteredPds == null) {filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);}checkDependencies(beanName, mbd, filteredPds, pvs);}
流程5 - applyPropertyValues
将上面自动装配的属性值设置到对象中。
首先是参数校验和安全机制处理
// 参数校验if (pvs.isEmpty()) {return;}// 安全机制特权处理if (System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) {((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());}
继续:判断属性是否已经准备好可以设置到对象中,如果已经准备好,那么就直接设置就完毕了;没有的话拿到原始的属性键值对继续处理。
MutablePropertyValues mpvs = null;List<PropertyValue> original;// 判断是否为MutablePropertyValues的实例if (pvs instanceof MutablePropertyValues) {mpvs = (MutablePropertyValues) pvs;// 默认情况下isConverted是falseif (mpvs.isConverted()) {// Shortcut: use the pre-converted values as-is.try {// 如果已经转换好了,那么直接设置属性值即可bw.setPropertyValues(mpvs);return;} catch (BeansException ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Error setting property values", ex);}}original = mpvs.getPropertyValueList();} else {// 获取属性键值对集合original = Arrays.asList(pvs.getPropertyValues());}
继续:获取值解析器,用于解析属性相关信息
// 获取类型转换器TypeConverter converter = getCustomTypeConverter();if (converter == null) {converter = bw;}// 值解析器BeanDefinitionValueResolver valueResolver= new BeanDefinitionValueResolver(this, beanName, mbd, converter);
继续:遍历每一个属性,创建属性的深拷贝
for (PropertyValue pv : original) {if (pv.isConverted()) {deepCopy.add(pv);} else {// 属性名称String propertyName = pv.getName();// 属性的原始值,可能是一个:RuntimeBeanNameReference<otherBean> 引用类型Object originalValue = pv.getValue();// 如果属性对象是AutowiredPropertyMarker的实例,那么获取其原始值if (originalValue == AutowiredPropertyMarker.INSTANCE) {Method writeMethod = bw.getPropertyDescriptor(propertyName).getWriteMethod();if (writeMethod == null) {throw new IllegalArgumentException("Autowire markerfor property without write method: " + pv);}originalValue = new DependencyDescriptor(new MethodParameter(writeMethod, 0), true);}// 利用值解析器获取值,并将其设置为已经转换好的属性值Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);Object convertedValue = resolvedValue;// 判断属性是否是可以转换的// 判断 bw.isWritableProperty(propertyName)// --是否有set方法// 判断 PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName)// --检查给定的属性是否为索引属性或嵌套属性boolean convertible = bw.isWritableProperty(propertyName) &&!PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);// 符合条件设置 convertedValueif (convertible) {convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);}// Possibly store converted value in merged bean definition,// in order to avoid re-conversion for every created bean instance.// 如果解析后的值和原始值是一样的if (resolvedValue == originalValue) {if (convertible) {pv.setConvertedValue(convertedValue);}deepCopy.add(pv);// 必须是字符串类型// 不是动态的字符串// 不是集合也不是数组} else if (convertible && originalValue instanceof TypedStringValue &&!((TypedStringValue) originalValue).isDynamic() &&!(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {pv.setConvertedValue(convertedValue);deepCopy.add(pv);// 其他情况} else {resolveNecessary = true;deepCopy.add(new PropertyValue(pv, convertedValue));}}}
最后,将属性设置到对象上
try {bw.setPropertyValues(new MutablePropertyValues(deepCopy));} catch (BeansException ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Error setting property values", ex);}
