概述
Spring 的属性填充主要是在 Bean 被创建后,通过 populateBean
方法来完成对象属性赋值以逐步完成 Bean 的初始化工作。
Spring 属性填充
Spring 属性填充过程,核心就是实现,对 @Value
、@Autowired
、@Resource
等属性或者方法修饰注解的依赖进行注入或者说是对于依赖对象的查找和填充过程。
@Value
,@Autowired
的处理类是通过AutowiredAnnotationBeanPostProcessor
处理的。@Resource
是通过CommonAnnotationBeanPostProcessor
处理 上述的两个类也是我们本文中所涉及到的核心类。
属性填充的入口方法DefaultListableBeanFactory#populateBean
, 下面我们就从入口方法开始一步步的解析Spring IOC
对 Bean 属性填充的过程。
populateBean 方法
下面是 populateBean
的流程
(1) InstantiationAwareBeanPostProcessor
处理器 postProcessAfterinstantiation
方法的行, 该方法执行后可以判断是否继续执行默认的属性填充处理。
(2) 根据注入类型(byName/byType),提取依赖的bean, 并且统一存入 PropertyValues
中
(3) 应用 InstantiationAwareBeanPostProcessor
处理器的 postProcessProperties
方法,在属性填充之间对属性的再次梳理,典型的就行 AutowiredAnnotationBeanPostProcessor
实现 @Autowried 注解的解析。
(4) 将 PropertyValues
中的属性填充到 BeanWrapper
中。
下面是源码中的处理过程
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
//...
//在属性被填充前,给 InstantiationAwareBeanPostProcessor 类型的后置处理器一个修改 bean 状态的机会。
//定义该类型的后置处理器,可以通过实现 InstantiationAwareBeanPostProcessorAdapter 抽象类完成。
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
}
// 从Bean定义里面把准备好的值都拿出来~~~
// 它是个MutablePropertyValues,持有N多个属性的值~~~
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
// 自动注入模式
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
// by_name 是根据属性名称查找 bean
// by_type 是根据属性类型查找 bean
// 查找到 bean 之后进行 set 注入
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;
// 总结:
// spring 自动注入通过某个类的 set 方法来查找 bean, byName 就是根据某个 set 方法所对应的属性名去查找 bean
// byType 就是根据某个 set 方法的参数去找 bean
// 如果目前采用注解的方式,很少使用到
}
// 执行完成 Spring 的自动注入之后,就开始解析 @Autowired . 这里叫做实例化回调
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
// @Autowired 注解的 AutowiredAnnotationBeanPostProcessor
// @Resource 注解的 CommonAnnotationBeanPostProcessor
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
// 调用 BeanPostProcessor 分别解析 @Autowired、@Resource、@Value 为属性注入值
// 此处会从后置处理,从里面把依赖的属性,值都拿到。AutowiredAnnotationBeanPostProcessor就是在此处拿出值的~~~
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) {
// 完成 pvs 赋值的运用
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
autowireByName
通过方法 beanName 来实现自动注入,因为在 Spring IOC 中beanName是唯一的, 所以这样的效率是最高的,复杂度最低,代码如下。
protected void autowireByName(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
//获取非简单类型属性的名称,且该属性未被配置在配置文件中
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
if (containsBean(propertyName)) {
// 根据属性名称去查找 bean, 这个就是 byName
Object bean = getBean(propertyName);
// 给属性赋值
pvs.add(propertyName, bean);
registerDependentBean(propertyName, beanName);
//.... print log
}
else {
//.... print log
}
}
}
autowireByType
通过类型来获取 Bean 进行注入,由于在 Spring IOC 中,同一个类型的 Bean 可以存在多个,对比 autowireByName
处理要复杂一些。
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);
//查找到有对应 set 方法的属性
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()) {
// set 方法中的参数信息
MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
// Do not allow eager init for type matching in case of a prioritized post-processor.
// 当前 bean 是否实现了 PriorityOrdered
boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered);
DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
// 根据 bean 类型找 bean, 这里是 byType
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);
}
}
}
通过上面的代码我们可以看到在这里的它的核心方法也就是 resolveDependency
。
resolveDependency
再 resolveDependency 方法中首先判断了依赖的类型, 然后在做对应的处理, 核心的方法是 doResolveDependency
。
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
// DependencyDescriptor 表示一个依赖,可以是一个属性字段,可能是一个构造方法参数,可能是一个 set 参数
// 根据 descriptor 去 BeanFactory 中找到 bean
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
// 如果是 Optional
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 {
// 在使用 @Autowired 注解时,也可以使用 @Lazy 注解,到时候注入的会是一个代理对象
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
if (result == null) {
// 通过解析 descriptor 找到 bean 对象
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
}
我们再来到 doResolveDependency
方法
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
// 如果 DependencyDescriptor 是一个 ShortcutDependencyDescriptor
// 那么会直接理解 beanName 从 beanFactory 中拿到一个 bean
// 在利用 @Autowired 注解来进行依赖注入时会利用 ShortcutDependencyDescriptor 来进行依赖注入的缓存
// 表示当解析完成某个依赖信息后,会把依赖的 bean 的 beanName 缓存起来
Object shortcut = descriptor.resolveShortcut(this);
if (shortcut != null) {
return shortcut;
}
// 获取 descriptor 的具体赖姓
Class<?> type = descriptor.getDependencyType();
// 1. 获取 @Value 注解中所配置的值
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor); //判断是否通过 @Value 指定了
if (value != null) {
if (value instanceof String) {
// 先进行占位符的填充,解析 "$" 符号
String strVal = resolveEmbeddedValue((String) value);
BeanDefinition bd = (beanName != null && containsBean(beanName) ?
getMergedBeanDefinition(beanName) : null);
// 解析 Spring EL 表达式, 解析 "#" 符号(可以是运算,也可以是某个 bean 的名字)
value = evaluateBeanDefinitionString(strVal, bd);
}
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
try {
return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
} catch (UnsupportedOperationException ex) {
// A custom TypeConverter which does not support TypeDescriptor resolution...
return (descriptor.getField() != null ?
converter.convertIfNecessary(value, type, descriptor.getField()) :
converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
}
}
//没有使用 @Value 注解
//2. 要注入的类型不是一个 Map,Array, Collection
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
//通过 Type 查找,可能找到多个, 这里的 value ,可能是具体的实例对象, 也能暂时只是 Class 对象
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
}
String autowiredBeanName;
Object instanceCandidate;
// 根据 type 查找到了多个
if (matchingBeans.size() > 1) {
// 如果找到了多个,去尝试确定出唯一的一个
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
if (autowiredBeanName == null) {
if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
//如果找到多个,并且依赖是 required , 或者不是数组或者 Collection 或者 Map
return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
} else {
// In case of an optional Collection/Map, silently ignore a non-unique case:
// possibly it was meant to be an empty collection of multiple regular beans
// (before 4.3 in particular when we didn't even look for collection beans).
return null;
}
}
instanceCandidate = matchingBeans.get(autowiredBeanName);
} else {
// We have exactly one match.
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
autowiredBeanName = entry.getKey();
instanceCandidate = entry.getValue();
}
if (autowiredBeanNames != null) {
autowiredBeanNames.add(autowiredBeanName);
}
if (instanceCandidate instanceof Class) {
// 调用 beanFactory.getbean() 创建 bean 对象
instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
}
Object result = instanceCandidate;
if (result instanceof NullBean) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
result = null;
}
if (!ClassUtils.isAssignableValue(type, result)) {
throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
}
return result;
} finally {
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
}
}
上面有我们的常用注入 @Value
, @Autowired
的处理,当我们同一个类型的 Bean 查找到多个结果的时候,我们来看如何选择的 determineAutowireCandidate
方法的实现。
protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
Class<?> requiredType = descriptor.getDependencyType();
// 取 @Primary 的 bean
String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
if (primaryCandidate != null) {
return primaryCandidate;
}
// 取优先级最高的 Bean 通过 @Priority 来定义优先级,数字越小,优先级越高
String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
if (priorityCandidate != null) {
return priorityCandidate;
}
// Fallback
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
String candidateName = entry.getKey();
Object beanInstance = entry.getValue();
if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) ||
// 根据属性名确定
matchesBeanName(candidateName, descriptor.getDependencyName())) {
return candidateName;
}
}
return null;
}
doResolveDependency 总结
(1) 首先调用 DefaultListableBeanFactory#doResolveDependency
方法中通过属性来获取对应的需要注入的 Bean 。
(2) 第一步解析 @Value
注解, 如果存在就解析 el 表达式获取 Bean 。
(3) 第二步解析 @Autowired
自动注入注解,如果存在首先就去解析这个注解。
(4) 通过依赖的类型去查找所有符合条件的候选 Bean。
(5) 当符合条件的 Bean 的个数为 0 的时候,判断 @Autowired
的 required 属性是否为 true, 如果是 true 那么就抛异常,提示找不到 Bean。
(6) 如果匹配到1个的时候,我们就直接使用。
(7) 如果匹配到多个的时候, 我们就需要做一下的选择:
首先遍历所有的候选 beanName, 判断是否有 @Primary
注解,如果有一个就返回,如果有多个会抛出异常 NoUniqueBeanDefinitionException
;
然后,遍历所有的候选 beanName, 判断是否有 @Priority
注解,如果有就按照自然顺序排序返回第一个,如果存在多个 Bean 优先级相同则抛出异常 NoUniqueBeanDefinitionException
( 注意:这里容易混淆 @Order
注解);
最后,遍历所有的候选 beanName,如果上述两种情况都不能选择到匹配的,那么将读取参数名通过 byName 的方式来匹配 Bean。
(8) 把所有的字段和需要注入的到 Bean 的属性之后完成属性的注入。
(9) 最后,若存在属性pvs,那就做赋值操作
applyPropertyValues
该方法主要是实现 pvs 的值的运用
(1) 检测属性值列表是否已转换过的,若转换过,则直接填充属性,无需再次转换
(2) 遍历属性值列表 pvs,解析原始值 originalValue,得到解析值 resolvedValue
(3) 对解析后的属性值 resolvedValue 进行类型转换
(4) 将类型转换后的属性值设置到 PropertyValue 对象中,并将 PropertyValue 对象存入 deepCopy 集合中将 deepCopy 中的属性信息注入到 bean 对象中
// 本方法传入了beanName和bean定义信息,以及它对应的BeanWrapper和value值
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
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;
// 若该mpvs中的所有属性值都已经转换为对应的类型,则把mpvs设置到BeanWrapper中,返回
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());
}
// 若调用者没有自定义转换器,那就使用BeanWrapper本身(因为BeanWrapper实现了TypeConverter 接口)
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
// 获取BeanDefinitionValueResolver,该Bean用于将bean定义对象中包含的值解析为应用于目标bean实例的实际值。
BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);
// Create a deep copy, resolving any references for values.
List<PropertyValue> deepCopy = new ArrayList<>(original.size());
boolean resolveNecessary = false;
// 遍历没有被解析的original属性值
for (PropertyValue pv : original) {
if (pv.isConverted()) {
deepCopy.add(pv);
}
else {// 被解析过的PropertyValue此处会一步步解析
String propertyName = pv.getName();
Object originalValue = pv.getValue();
// 解析各式各样的值
Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
Object convertedValue = resolvedValue;
// 属性可写 并且 不是嵌套(如foo.bar,java中用getFoo().getBar()表示)或者索引(如person.addresses[0])属性
boolean convertible = bw.isWritableProperty(propertyName) &&
!PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
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));
}
}
}
// 标记mpvs已经转换
if (mpvs != null && !resolveNecessary) {
mpvs.setConverted();
}
// Set our (possibly massaged) deep copy.
// 使用转换后的值进行填充
try {
// 对属性的值进行注入
bw.setPropertyValues(new MutablePropertyValues(deepCopy));
}
catch (BeansException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Error setting property values", ex);
}
}