使用属性值填充给定 BeanWrapper 中的 bean 实例。
概要流程图
@SuppressWarnings("deprecation") // for postProcessPropertyValues
protected 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 {
@Override
public 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"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://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")
@Test
public 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);
// 获取属性的注入类型,默认情况下为0
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;
}
当在配置文件中指定了注入类型才会进入这个分支。
比如:
根据名称获取属性 autowireByName
protected void autowireByName(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
// 过滤得到需要根据名称注入的属性
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
// 判断依赖的属性是否有指定的bean
if (containsBean(propertyName)) {
// 得到依赖的bean
Object bean = getBean(propertyName);
// 加入pvs
pvs.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"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://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("测试根据属性名称注入")
@Test
public 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是false
if (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 marker
for 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);
// 符合条件设置 convertedValue
if (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);
}