spring5源码篇(5)——bean的依赖注入之setter注入、field注入
spring-framework 版本:v5.3.19
文章目录
- populateBean
- PropertyValues
- @Autowired
- findAutowiringMetadata
- InjectionMetadata#inject
- InjectedElement#inject
- DefaultListableBeanFactory#resolveDependency
- findAutowireCandidates 匹配bean
- determineAutowireCandidate 推断bean
- 总结
话不多说直接上代码
populateBean
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 {
return;
}
}
//InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
// byName,byType自动注入
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
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();
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
// @Autowired自动注入
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
pvsToUse = bp.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);
}
}
PropertyValues
在填充属性的时,会先把bean的属性以及其对应的值存到 PropertyValues(下面简称pvs),最后再调用applyPropertyValues方法将其注入到bean示例。那么PropertyValues的值从哪里来?
实际上这里所说的属性并不是以字段为维度的,而是以“set”开头的方法为维度。即假如存在setXXX方法,那就认定有XXX这么一个属性。在对应属性注入时就会执行这个set方法。这也是为什么必须要有set方法的原因,没有set方法spring就不知道有这个属性。
硬编码beanDefinition设值的
beanDefinition.getPropertyValues().add("string", 1);
xml手动注入的
<bean id="xmlUser" class="entity.XmlUser">
<property name="componentUser" ref="comUser"/>
</bean>
autowireMode = byName/byType 自动注入的
<bean id="xmlUser" class="entity.XmlUser" autowire="byName"/>
//或
@Bean(autowire = Autowire.BY_NAME)
public BeanUser user() {
return new BeanUser();
}
注意:上面的autowireMode是beanDefinition中的一个属性,默认为NO表示不自动注入。与我们常用的@Autowired注解没有什么直接关系,即使加了@Autowired也不会更改autowireMode属性的值,非要说有关系也是@Autowired是autowireMode在功能上都可以实现自动注入。
硬编码和xml配置的属性值在创建beanDefinition时就已经去寻找对应属性值add到pvs了,而autowireMode自动注入的属性值是在执行populateBean方法时才会去处理得到一个新的pvs。
// 硬编码beanDefinition设值的、xml手动注入的都已经在pvs中了
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
// byName,byType自动注入
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
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;
}
autowireByName、autowireByType就分别根据name、type去getBean然后add到pvs,最后apply就实现属性值的注入了。
@Autowired
那么@Autowired的值是怎么注入的?
回到populateBean方法
// @Autowired自动注入
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
没错,就是通过BeanPostProcessor去增强的,说具体一点是一个InstantiationAwareBeanPostProcessor再具体一点就是AutowiredAnnotationBeanPostProcessor(这也是之前说的和autowireMode没有关系的证据,@Autowired并不是去修改autowireMode属性值,而是通过AutowiredAnnotationBeanPostProcessor增强实现的)
上代码AutowiredAnnotationBeanPostProcessor#postProcessProperties
findAutowiringMetadata
这个方法就是寻找类中有@Autowired、@Value、@Inject注解的属性或者方法,并且将其封装成InjectionMetadata存到injectionMetadataCache缓存中表示所有注入点。
实际上这个方法在之前的MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition就已经调用了,后续直接调用直接在缓存取值而已
public class InjectionMetadata {
//...
private final Collection<InjectedElement> injectedElements;
@Nullable
private volatile Set<InjectedElement> checkedElements;
//...
}
injectedElements指的是当前类中所有被找到的属性和方法。
checkedElements是injectedElements中被注册到BeanDefinition的externallyManagedConfigMembers中的元素。
注入时优先用checkedElements
InjectionMetadata#inject
然后遍历所有的注入点执行inject方法
InjectedElement#inject
实际上这个方法有2个重写,分别是AutowiredFieldElement和AutowiredMethodElement,相对应的是注解在属性上和注解在方法上。
AutowiredFieldElement
找到bean后通过反射得到field set值。
AutowiredMethodElement
找到bean后通过反射得到set方法传递参数执行。
注意:AutowiredMethodElement会跳过pvs中已有值的属性
DefaultListableBeanFactory#resolveDependency
无论是setter注入还是属性注入,最后在匹配bean的时候都会调用到DefaultListableBeanFactory#resolveDependency去匹配。
这个方法的匹配逻辑直接决定了@Autowired注入哪个bean。
doResolveDependency
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
//依赖注入的缓存,有缓存直接返回
Object shortcut = descriptor.resolveShortcut(this);
if (shortcut != null) {
return shortcut;
}
Class<?> type = descriptor.getDependencyType();
//@Value情况获取所指定的值
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
if (value != null) {
if (value instanceof String) {
//如果是string,解析占位符(${})
String strVal = resolveEmbeddedValue((String) value);
BeanDefinition bd = (beanName != null && containsBean(beanName) ?
getMergedBeanDefinition(beanName) : null);
//解析spring 表达式(#{})
value = evaluateBeanDefinitionString(strVal, bd);
}
//value 类型转化
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()));
}
}
//数组、Map、集合情况
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
//根据类型去匹配(如果有@Qualifier注解,这里也会作为匹配条件)
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
}
String autowiredBeanName;
//这里匹配到的可能是bean对象也可能是bean class。当没有示例化时就是bean class
Object instanceCandidate;
//如果匹配到多个就由spring自动推断
if (matchingBeans.size() > 1) {
//推断顺序 @Primary --> @Priority高优先级的优先 --> match name
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
if (autowiredBeanName == null) {
//如果推断不出来
if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
//如果require是true或type不是数组,集合,map则报错
return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
}
else {
return null;
}
}
instanceCandidate = matchingBeans.get(autowiredBeanName);
}
//如果只有一个那就是这个了
else {
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
autowiredBeanName = entry.getKey();
instanceCandidate = entry.getValue();
}
//记录匹配过的BeanName
if (autowiredBeanNames != null) {
autowiredBeanNames.add(autowiredBeanName);
}
//如果还没实例化,则获取bean,这一步里面会调用getBean
if (instanceCandidate instanceof Class) {
instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
}
Object result = instanceCandidate;
//NullBean的情况
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);
}
}
findAutowireCandidates 匹配bean
匹配逻辑
- 根据type找到所有beanName
- 遍历beanName筛选 SimpleAutowireCandidateResolver->GenericTypeAwareAutowireCandidateResolve->QualifierAnnotationAutowireCandidateResolver
- 为空考虑回退匹配
- 还是为空考虑匹配自己
大部分场景1,2就能匹配出来了
protected Map<String, Object> findAutowireCandidates(
@Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
//匹配当前类型所有的beanName
String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this, requiredType, true, descriptor.isEager());
Map<String, Object> result = CollectionUtils.newLinkedHashMap(candidateNames.length);
for (Map.Entry<Class<?>, Object> classObjectEntry : this.resolvableDependencies.entrySet()) {
Class<?> autowiringType = classObjectEntry.getKey();
if (autowiringType.isAssignableFrom(requiredType)) {
Object autowiringValue = classObjectEntry.getValue();
autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);
if (requiredType.isInstance(autowiringValue)) {
result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);
break;
}
}
}
//遍历beanName交由autowireCandidateResolver筛选
//责任链:QualifierAnnotationAutowireCandidateResolver->GenericTypeAwareAutowireCandidateResolver->SimpleAutowireCandidateResolver
for (String candidate : candidateNames) {
if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
if (result.isEmpty()) {
boolean multiple = indicatesMultipleBeans(requiredType);
// 为空考虑回退匹配
DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();
for (String candidate : candidateNames) {
if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, fallbackDescriptor) &&
(!multiple || getAutowireCandidateResolver().hasQualifier(descriptor))) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
if (result.isEmpty() && !multiple) {
//还是为空考虑匹配自己
for (String candidate : candidateNames) {
if (isSelfReference(beanName, candidate) &&
(!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate)) &&
isAutowireCandidate(candidate, fallbackDescriptor)) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
}
}
return result;
}
determineAutowireCandidate 推断bean
推断顺序 @Primary --> 优先级最高 --> match name
protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
Class<?> requiredType = descriptor.getDependencyType();
//有@Primary优先
String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
if (primaryCandidate != null) {
return primaryCandidate;
}
//@Priority高优先级的优先
String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
if (priorityCandidate != null) {
return priorityCandidate;
}
// match name
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、处理@Value
2、处理数组、Map、集合情况
3、先根据类型去匹配,如果只有一个那就是这个
4、反之在多个匹配的bean中由spring自动推断一个,推断顺序:@Primary,@Priority,match name
至此@Autowired注解的属性就自动注入进去了。相对于前面修改autowireMode为byType/byName的自动注入还是复杂很多的,毕竟这里不只是简单的先byType后byName(只是日常大部分情况的使用场景等效于这样)。
总结
这里所分析到的依赖注入写法有 硬编码手动注入、xml手动注入、autowireMode byName/byType自动注入、@Autowired field自动注入、@Autowired setter自动注入。前面三种方式都是通过修改pvs最后再应用到bean实例上,而@Autowired是通过AutowiredAnnotationBeanPostProcessor直接增强bean实例。@Autowired注入的顺序如下,处理 @Value -> 处理数组、Map、集合情况 -> 匹配:(byType ->SimpleAutowireCandidateResolver筛选->GenericTypeAwareAutowireCandidateResolve筛选->QualifierAnnotationAutowireCandidateResolver筛选) -> 推断:(@Primary -> @Priority -> by name)
除此之外还可以通过指定构造参数 | autowireMode设成constructor | @Autowired构造方法 也可以实现依赖注入(也即构造器注入,下篇分析)。由此可见无论是自动注入还是手动注入,写法都有很多种,但无论是哪种写法,从原理上看都离不开 setter注入,属性注入,构造器注入。