一、介绍
Spring 如何将Bean 的属性依赖关系注入Bean 实例对象中的,本章主要分析
AbstractAutowireCapableBeanFactory#populateBean
Spring 版本:5.2.10.RELEASE
二、源码及流程分析
2.1 populateBean 方法 流程图及步骤
主要步骤为:
- 先判断 是否BeanWrapper 是否为null, 如果为null ,并且有属性,那就报错
- 判断是否 是合成的,并且是否有 InstantiationAwareBeanPostProcessor 类型的后置处理器需要处理,如果需要,那就 执行对应的 postProcessAfterInstantiation 方法
- 根据注入类型判断 是否需要 按照 ByName 还是 ByType 注入
- 判断是否有 InstantiationAwareBeanPostProcessor 类型的后置处理器需要处理,如果需要,那就 执行对应的 postProcessProperties 方法 ,这个方法主要是对 相关注解 属性的处理,详见 spring源码解析之—InstantiationAwareBeanPostProcessor解析
- 判断是否有依赖dependency-check ,以及相关的依赖检查 ,详细在后面介绍
- 进行属性转换和填充,详细下面解释
2.2 源码分析
2.2.1 populateBean方法
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
// 校验,如果为null 并且有属性值,抛出异常
if (bw == null) {
if (mbd.hasPropertyValues()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
}
else {
// 跳过空实例的属性填充阶段
return;
}
}
/**
这里是判断是否有 hasInstantiationAwareBeanPostProcessors ,并且是系统自定义的(没有代理) 这样就可以再填充属性之前 还有机会 进行一些调整
主要就是运行 postProcessAfterInstantiation 实例化(不是初始化)之后的后置处理器
*/
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
// 这里需要留意有一个 返回 false , 那就直接返回
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
}
/**
获取属性, MutablePropertyValues 类型
PropertyValues接口的默认实现。允许对属性进行简单的操作,并提供构造函数来支持从Map中进行深度复制和构造
*/
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
// 获取注入类型,默认是0(AUTOWIRE_NO),如果不是by_name或者 by_type, 那就不走以下逻辑
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
// by_type 或者 by_name 类型,先 深度拷贝 一个对象
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
//根据名称注册
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
//根据类型注册
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
/**
判断是否需要依赖检查
dependency-check 是在spirng 2.x 里面使用的属性,用来指定是否需要检验 属性是否赋值, 但是在 spring 3.x + 以后的
版本已经放弃了, 后续的版本建议在 setter 方法上使用@Required ,但是 @Required在 spring 5.1 之后的版本又被废弃了
dependency-check 有四种类型,none (默认就是none), simple,object,all
所以当前版本是 5.2.10.RELEASE, 个人认为这里应该是默认的 none, needsDepCheck 为false
这里 加这类的判断,应该是为了兼容以前的配置吧
**/
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
for (BeanPostProcessor bp : getBeanPostProcessors()) {
/**
这里主要是 来 对 @Resource , @Autowired, @Value ,@Inject 等注解 进行
注入,这里主要是两个类CommonAnnotationBeanPostProcessor,AutowiredAnnotationBeanPostProcessor
详细的内容可以查看上面的解释
**/
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
/**
对属性进行过滤, 这里主要是过滤三种
1. CGLIB method 代理的需要过滤掉
2. 需要忽略掉的类型, 比如 String
3. 需要过忽略的接口类型, 比如 一些Aware 类型的接口
*/
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
// postProcessPropertyValues 已经被放弃了, 这样应该是出于兼容性的考虑
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);
}
}
2.2.2 dependency-check
在 Bean创建的时候,有时需要强制检测属性是否已经赋值, 这里就可以使用dependency-check .
dependency-check 是在 spring 2.x 里面有的,spring 3 + 后续都没有了,有时源码里面 可能为了兼容以前的版本,有一定的冗余代码,既然源码里面涉及到了,我们就 简单了解一下.
dependency-check 一共有4个类型:
- none :不检查,默认就是 none
- simple :只检查简单类型属性以及集合类型属性
- objects :检查除简单类型属性以及集合类型属性外的引用类型属
- all : 所有类型
此外我们在spring 5.2.10.RELEASE 里面,即使配置 了spring-beans-2.5.xsd ,也是不能使用这个标签的,
spring在加载xsd文件时总是先试图在本地查找xsd文件(spring的jar包中已经包含了所有版本的xsd文件),如果没有找到,才会转向去URL指定的路径下载。spring的jar包里,在META-INF目录下都有一个spring.schemas,这里指定了对应的文件路径,这里将所有的版本都指向了本地的spring-beans.xsd ,但是本地的spring-beans.xsd 是没有支持这个 属性的
可以用 @Required注解 代替, 详细可见Spring源码解析之–@Required详解
2.2.3 filterPropertyDescriptorsForDependencyCheck
有一些版本 没有这个方法, 主要就是忽略过滤掉一些 属性的注入
- CGLIB method 代理的需要过滤掉
- 需要忽略掉的类型
- 需要过滤掉的接口类型, 类似一些 Aware ,如 BeanNameAware
比如AbstractAutowireCapableBeanFactory 构建的时候,就会加一下 需要忽略的依赖接口类型,ignoreDependencyType 的范围比 ignoreDependencyInterface 的范围大一些.
2.2.4 postProcessProperties
InstantiationAwareBeanPostProcessor 里面有一个 对带有注解的属性 进行注入,这里主要 是两个类
- CommonAnnotationBeanPostProcessor : 主要是对 @Resource 注解进行 注入
- AutowiredAnnotationBeanPostProcessor : 主要是对 @Autowired ,@Value,@Lookup, @Inject 注解进行注入
详细文章 spring源码解析之—InstantiationAwareBeanPostProcessor解析
2.2.5 autowireByName方法
大致思路:
- 获取需要依赖注入的属性
- 对属性进行遍历, 首先判断是否已经包含在 容器中(包括未初始化完成的,排查 BeanFactory类型)
- 获取对应的Bean ,放入到pvs 里面,并完善 器对应的依赖和被依赖关系
autowireByName 过程还是比较简单的, 就是通过 name 去容器中获取(调用getBean),容器中 的缓存就是 用 bean name 作为key
protected void autowireByName(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
//返回bw 中需要依赖注入的属性,unsatisfiedNonSimpleProperties 详细解析如下
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
// 对属性进行遍历
for (String propertyName : propertyNames) {
/** 判断容器里面是否包含对应的bean,详细判断在后面
如果存在,那就取出并加入pvs 里面.
注册依赖关系, 主要是 放入dependentBeanMap 和 dependenciesForBeanMap 中
其中 dependentBeanMap : 是当前bean被引用依赖的 bean
dependenciesForBeanMap :当前Bean所依赖的Bean的集合
**/
if (containsBean(propertyName)) {
Object bean = getBean(propertyName);
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");
}
}
}
}
@Override
public boolean containsBean(String name) {
// 对beanName 进行最终转换
String beanName = transformedBeanName(name);
/** 判断容器中是否 含有 beanName对应的 bean ,没有完全初始化完的也算
这里需要排除BeanFactory 类型 , factoryBean 类型的也算
如果没有找到,就去 父BeanFactory 里面寻找
*/
if (containsSingleton(beanName) || containsBeanDefinition(beanName)) {
return (!BeanFactoryUtils.isFactoryDereference(name) || isFactoryBean(name));
}
// Not found -> check parent.
BeanFactory parentBeanFactory = getParentBeanFactory();
return (parentBeanFactory != null && parentBeanFactory.containsBean(originalBeanName(name)));
}
2.2.6 autowireByType方法
大致思路:
- 获取类型转换器,如果没有,默认为 bw
- 获取需要注入的属性
- 对所有属性进行遍历,开始 注入, 首先排除 Object.class 类型,调用resolveDependency 方法进行校验获取对应的最后的值
- 放入 pvs 里面,并 注册对应的依赖和被依赖关系
protected void autowireByType(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
// 获取自定义的类型转换器, 如果为null, 那就 使用bw ,BeanWrapper 是继承了 TypeConverter 类型的
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
// 获取需要注入的 propertyNames
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.
// 这里首先排除 Object.class 类型,毫无意义
if (Object.class != pd.getPropertyType()) {
// 获取指定属性的setter 方法,包装成 MethodParameter 类型
MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
// Do not allow eager init for type matching in case of a prioritized post-processor.
//判断实例是否需要紧急加载,是否实现了PriorityOrdered接口
boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered);
DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
/**
解析指定beanName的属性所匹配的值,并把解析到属性名称存储在
autowiredBeanNames中当属性存在多个封装bean 时如:
@Autowired private List<A> aList; 将会找到所有匹配A类型的bean 并将其注入, 详细流程在下面分析
**/
Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
//加入到 pvs里面
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);
}
}
}
2.2.7 unsatisfiedNonSimpleProperties方法
返回未满足要求的非简单bean属性数组
大致思想:
- 获取所有输入的属性
- 获取bw 里面所有的属性
- 遍历所有属性,返回未满足要求的非简单bean属性数组(不包含简单l类型属性,如字符串) ,如下4个条件
3.1 setter 方法不为空
3.2 确定给定的bean属性是否被排除在依赖性检查之外,这里主要是判断是否是CGLIB 代理的属性 ,是否在忽略依赖类型里面,是否是指定的忽略依赖接口
3.3 给出的属性填充值里面是不是包括对应的属性名称
3.4 属性是不是简单类型的属性
protected String[] unsatisfiedNonSimpleProperties(AbstractBeanDefinition mbd, BeanWrapper bw) {
Set<String> result = new TreeSet<>();
// 获取所有输入的属性
PropertyValues pvs = mbd.getPropertyValues();
// 获取所有属性的描述
PropertyDescriptor[] pds = bw.getPropertyDescriptors();
for (PropertyDescriptor pd : pds) {
/**
这里便是判断是否满足条件
1. 属性没有对应的setter 方法
2. 确定给定的bean属性是否被排除在依赖性检查之外,这里主要是判断是否是CGLIB 代理的属性 ,是否在忽略依赖类型里面,是否是指定的忽略依赖接口
3. 给出的属性填充值里面是不是包括对应的属性名称
4. 属性是不是简单类型的属性
*/
if (pd.getWriteMethod() != null && !isExcludedFromDependencyCheck(pd) && !pvs.contains(pd.getName()) &&
!BeanUtils.isSimpleProperty(pd.getPropertyType())) {
result.add(pd.getName());
}
}
return StringUtils.toStringArray(result);
}
/** 是否被排除在依赖性检查之外
1. 判断此属性是否是CGLIB 代理的属性
2. 是否在忽略依赖类型 ignoredDependencyTypes 里面
3. 是否是指定的忽略依赖接口ignoredDependencyInterfaces 里面
*/
protected boolean isExcludedFromDependencyCheck(PropertyDescriptor pd) {
return (AutowireUtils.isExcludedFromDependencyCheck(pd) ||
this.ignoredDependencyTypes.contains(pd.getPropertyType()) ||
AutowireUtils.isSetterDefinedInInterface(pd, this.ignoredDependencyInterfaces));
}
2.2.8 applyPropertyValues方法
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
// 如果属性列表为null,直接返回
if (pvs.isEmpty()) {
return;
}
if (System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) {
((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
}
MutablePropertyValues mpvs = null;
List<PropertyValue> original;
// pvs 默认是 MutablePropertyValues 类型,获取属性列表
if (pvs instanceof MutablePropertyValues) {
mpvs = (MutablePropertyValues) pvs;
/**
判断属性是否已经转换过 ,如果已经转换过,直接赋值,并返回
*/
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());
}
// 获取自定义转换类型,如果为null ,使用默认的bw, BeanWrapper 类继承了 TypeConverter
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);
// 这里是创建一个 深度拷贝的list,解决值引用相关的问题
List<PropertyValue> deepCopy = new ArrayList<>(original.size());
boolean resolveNecessary = false;
for (PropertyValue pv : original) {
/** 如果子属性已经转换过,直接添加到 deepcopy list 里面
如果还没有转换,那就先获取
*/
if (pv.isConverted()) {
deepCopy.add(pv);
}
else {
String propertyName = pv.getName();
Object originalValue = pv.getValue();
/**
AutowiredPropertyMarker ,就是一个简单的标记类, 如果是 AutowiredPropertyMarker 类型,
那就获取对应的set方法,在通过DependencyDescriptor 包装一下, 在后面的 resolveValueIfNecessary 方法里面进行
解析转换
*/
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;
//检查给定的属性是否可写, 或者检查属性是否是索引或嵌套的属性,比如a.b , 或者 [a,b]
boolean convertible = bw.isWritableProperty(propertyName) &&
!PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
if (convertible) {
// 进行类型转换
convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
// 将转换转换的值保存在pv 里面,同时加到 深度拷贝list里面
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));
}
}
}
// 设置为已经转换过,避免后续的转换
if (mpvs != null && !resolveNecessary) {
mpvs.setConverted();
}
try {
// 这里就是 最后将转换后的值 进行赋值填充
bw.setPropertyValues(new MutablePropertyValues(deepCopy));
}
catch (BeansException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Error setting property values", ex);
}
}
2.2.9 DefaultListableBeanFactory#resolveDependency方法
根据此工厂中定义的bean解析指定的依赖关系
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
if (Optional.class == descriptor.getDependencyType()) {
return createOptionalDependency(descriptor, requestingBeanName);
}
else if (ObjectFactory.class == descriptor.getDependencyType() ||
ObjectProvider.class == descriptor.getDependencyType()) {
return new DependencyObjectProvider(descriptor, requestingBeanName);
}
else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
}
else {
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
if (result == null) {
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
}
三、小结
大致分析了 属性填充方法populateBean 的流程和 源码.