初识Spring源码 -- doResolveDependency | findAutowireCandidates | @Order@Priority调用排序 | @Autowired注入(代码片段
Posted 做猪呢,最重要的是开森啦
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了初识Spring源码 -- doResolveDependency | findAutowireCandidates | @Order@Priority调用排序 | @Autowired注入(代码片段相关的知识,希望对你有一定的参考价值。
0. 举个栗子:
@Component
public class SetterBean {
@Autowired
@Qualifier("beanService")
private BeanService beanService;
}
@Configuration
public class ConfigurationBean {
@Bean(autowireCandidate = false)
public BeanService beanService1() {
return new BeanServiceImpl();
}
@Bean
public BeanService beanService() {
BeanServiceImpl beanService = new BeanServiceImpl();
beanService.setName("zhangsan");
return beanService;
}
}
3. doResolveDependency:
上一篇文章介绍了populateBean属性填充方法,其中通过resolveDependency方法来解析出依赖的属性bean对象,再进行反射
·
而resolveDependency通常又调用doResolveDependency
来解析出依赖的属性bean对象
·
针对上述栗子,下文省略一些不必要的内容(注入集合、@Value的场景),后面再介绍.
@Nullable
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
//设置当前的descriptor(存储了方法参数等信息)为当前注入点
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
Object shortcut = descriptor.resolveShortcut(this);
if (shortcut != null) {
return shortcut;
}
//从descriptor中获取属性类型
Class<?> type = descriptor.getDependencyType();
... ... .... // 省略一些不必要的内容(注入集合、@Value的场景)代码
// 查找符合注入属性类型的bean,下文3.1有介绍
// 这里过滤了 @Bean(autowireCandidate = false)和不符合@Qualifier("beanName")的bean
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
// 为空说明找不到该注入类型的bean,如果注入的属性又是必须的,则抛NoSuchBeanDefinitionException
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
}
String autowiredBeanName;
Object instanceCandidate;
// 查找到多个符合注入属性类型的bean
if (matchingBeans.size() > 1) {
// 再过滤找到最优的beanName,进而获取最优的用来创建实例的候选者instanceCandidate
// 这里挑选@primary、@Priority等优先级高的bean,细节见下文3.3
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
if (autowiredBeanName == null) {
// 找不到最优的beanName,注入的属性又是必须的,则抛NoUniqueBeanDefinitionException异常
// 注入的属性非必须,未过滤前就有多个注入属性类型的bean,如果注入的属性不是集合,也抛异常
if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
}
else {
return null;
}
}
// 根据beanName获取最优的用来创建属性实例的候选者instanceCandidate
// key:beanName;value:符合注入属性类型的bean或者bean类型
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) {
// resolveCandidate调用getBean(),根据候选beanName进行属性bean的系列生命周期后返回完整的属性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);
}
}
3.1. findAutowireCandidates:
这里查找符合注入属性类型的bean,会过滤@Bean(autowireCandidate = false)和不符合@Qualifier(“beanName”)的bean
·
像本栗子的beanService1就会被过滤掉,具体过滤细节见下文3.2
protected Map<String, Object> findAutowireCandidates(
@Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
// 获取给定类型的所有beanName,包括在祖先工厂中定义的beanName
String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this, requiredType, true, descriptor.isEager());
Map<String, Object> result = new LinkedHashMap<>(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;
}
}
}
// isSelfReference 判断是否是自引用,即注入属性为自身类型
// isAutowireCandidate 判断是否有资格作为依赖注入的候选者,@Bean(autowireCandidate = false)注解的bean就没有资格
for (String candidate : candidateNames) {
if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
// 不是自引用又有资格,封装result,见下文3.4.1
//(key:beanName;value:符合注入属性类型的bean或者bean类型)
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
// 没有符合注入属性类型的beanName
if (result.isEmpty()) {
// 注入的属性是否是bean的集合类型,本栗子不是
boolean multiple = indicatesMultipleBeans(requiredType);
// 使用备用的依赖描述器再去获取一遍符合注入属性类型的beanName
DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();
for (String candidate : candidateNames) {
if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, fallbackDescriptor) &&
(!multiple || getAutowireCandidateResolver().hasQualifier(descriptor))) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
// 还是没有符合注入属性类型的beanName,又不是集合类型,考虑自引用,符合条件则将候选者添加到result中
if (result.isEmpty() && !multiple) {
// Consider self references as a final pass...
// but in the case of a dependency collection, not the very same bean itself.
for (String candidate : candidateNames) {
if (isSelfReference(beanName, candidate) &&
(!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate)) &&
isAutowireCandidate(candidate, fallbackDescriptor)) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
}
}
return result;
}
3.2. isAutowireCandidate:
该方法最后会调用AutowireCandidateResolver解析器的resolver.isAutowireCandidate方法来解析候选者bean是否有注入资格
protected boolean isAutowireCandidate(String beanName, RootBeanDefinition mbd,
DependencyDescriptor descriptor, AutowireCandidateResolver resolver) {
String bdName = BeanFactoryUtils.transformedBeanName(beanName);
resolveBeanClass(mbd, bdName);
if (mbd.isFactoryMethodUnique && mbd.factoryMethodToIntrospect == null) {
new ConstructorResolver(this).resolveFactoryMethodIfPossible(mbd);
}
BeanDefinitionHolder holder = (beanName.equals(bdName) ?
this.mergedBeanDefinitionHolders.computeIfAbsent(beanName,
key -> new BeanDefinitionHolder(mbd, beanName, getAliases(bdName))) :
new BeanDefinitionHolder(mbd, beanName, getAliases(bdName)));
return resolver.isAutowireCandidate(holder, descriptor);
}
在了解isAutowireCandidate前,先了解AutowireCandidateResolver接口实现类的AutowireCandidateResolver方法,类图如下:
3.2.1. SimpleAutowireCandidateResolver#isAutowireCandidate:
SimpleAutowireCandidateResolver 是一个简单的解析器,直接取bd.autowireCandidate值,默认为true,也就是可注入
·
本栗子beanService1使用 @Bean(autowireCandidate = false),即这个bean的autowireCandidate为false,不可注入
public boolean isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) {
return bdHolder.getBeanDefinition().isAutowireCandidate();
}
3.2.2. GenericTypeAwareAutowireCandidateResolver#isAutowireCandidate:
GenericTypeAwareAutowireCandidateResolver 是一个泛型依赖的解析器
- 先调用父类SimpleAutowireCandidateResolver来判断该候选bean是否可注入,允许则进行泛型匹配
- 主要在checkGenericTypeMatch方法匹配泛型:
- 如果待依赖注入的属性类型不包含泛型,直接返回true,即这个候选bean允许取注入,本栗子不涉及泛型,返回true
public boolean isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) {
if (!super.isAutowireCandidate(bdHolder, descriptor)) {
return false;
}
return checkGenericTypeMatch(bdHolder, descriptor);
}
3.2.3. QualifierAnnotationAutowireCandidateResolver#isAutowireCandidate:
QualifierAnnotationAutowireCandidateResolver是处理@Qualifier注解的解析器
- 先调用父类(即上述候选解析器)判断是否允许注入、泛型匹配
- 都满足则进行待依赖注入属性的@Qualifier匹配,匹配成功返回true,即这个候选bean允许注入
public boolean isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) {
// 父类校验:判断是否允许注入、泛型匹配
boolean match = super.isAutowireCandidate(bdHolder, descriptor);
if (match) {
// checkQualifiers来校验@Qualifier规则,第二个参数传属性注解信息数组
// bdHolder相当于候选bean,即符合属性类型的bean;descriptor是待依赖注入属性bean的描述器
match = checkQualifiers(bdHolder, descriptor.getAnnotations());
// 进一步校验标注在构造函数或方法上的@Qualifier注解规则
if (match) {
MethodParameter methodParam = descriptor.getMethodParameter();
// 如果当前是依赖注入属性,methodParam=null,注解返回match
if (methodParam != null) {
Method method = methodParam.getMethod();
// 校验标注在构造函数或方法上的@Qualifier注解规则
if (method == null || void.class == method.getReturnType()) {
match = checkQualifiers(bdHolder, methodParam.getMethodAnnotations());
}
}
}
}
return match;
}
3.2.4. checkQualifiers:
循环遍历属性上的注解,看是否是@Qualifier,是的话通常会取匹配注解的属性值是否和属性beanName一致
·
一致则不需要进行元注解匹配,否则会遍历一层元注解,进行元注解匹配,因为Spring还支持@Qualifier派生注解
·
关于元注解可以参考:链接的3.3的内容
protected boolean checkQualifiers(BeanDefinitionHolder bdHolder, Annotation[] annotationsToSearch) {
if (ObjectUtils.isEmpty(annotationsToSearch)) {
return true;
}
SimpleTypeConverter typeConverter = new SimpleTypeConverter();
// 遍历属性注解信息数组
for (Annotation annotation : annotationsToSearch) {
Class<? extends Annotation> type = annotation.annotationType();
boolean checkMeta = true;
boolean fallbackToMeta = false;
// 判断是不是@Qualifier注解
if (isQualifier(type)) {
// 通常会取匹配注解的属性值是否和候选bean的beanName一致
if (!checkQualifier(bdHolder, annotation, typeConverter)) {
// 表示第一次匹配失败,进而往下进行元注解匹配
fallbackToMeta = true;
}
else {
// 匹配成功,就不用往下进行元注解匹配
checkMeta = false;
}
}
// 本身不是@Qualifier或匹配失败都会进行元注解匹配
if (checkMeta) {
boolean foundMeta = false;
// 遍历元注解,也就是注解里的注解。只遍历一层元注解
for (Annotation metaAnn : type.getAnnotations()) {
Class<? extends Annotation> metaType = metaAnn.annotationType();
// 判断元注解是不是@Qualifier注解
if (isQualifier(metaType)) {
foundMeta = true;
// 元注解匹配
if ((fallbackToMeta && StringUtils.isEmpty(AnnotationUtils.getValue(metaAnn))) ||
!checkQualifier(bdHolder, metaAnn, typeConverter)) {
return false;
}
}
}
// 两次都匹配失败,则false
if (fallbackToMeta && !foundMeta) {
return false;
}
}
}
return true;
}
3.2.5. isAutowireCandidate小结:
该方法最后会调用resolver.isAutowireCandidate,经过不同的解析器去处理,返回true即这个候选bean可以注入:
- 简单候选解析器去判断autowireCandidate是否是true
- 泛型候选解析器去匹配泛型,本栗子不是泛型返回true
- @Qualifier注解的解析器去匹配@Qualifier规则(通常匹配属性是否是@Qualifier注解和注解属性值),匹配成功返回true
3.3. determineAutowireCandidate:
经过findAutowireCandidates匹配(也就是autowireCandidate和@Qualifier匹配)后,还存在多个候选bean
·
则在此处筛选出最优的候选bean,涉及@Primary、@Priority注解
protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
// 获取待依赖注入属性的类型
Class<?> requiredType = descriptor.getDependencyType();
// 先匹配候选bean是有@Primary
String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
// 通过@Primary成功,返回候选bean的beanName
if (primaryCandidate != null) {
return primaryCandidate;
}
// @Primary匹配失败,再通过@Priority进行优先级匹配,属性值越小优先级越高
String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
// @Priority高优先级匹配成功,返回候选bean的beanName
if (priorityCandidate != null) {
return priorityCandidate;
}
// @Primary、@Priority都匹配失败,最后匹配候选beanName和属性beanName是否一致,一致则返回候选bean的beanName
for (Map.Entry<String, Object> entry : candid以上是关于初识Spring源码 -- doResolveDependency | findAutowireCandidates | @Order@Priority调用排序 | @Autowired注入(代码片段的主要内容,如果未能解决你的问题,请参考以下文章
初识Spring源码 -- applyMergedBeanDefinitionPostProcessors
初识Spring源码 -- initializeBean | @PostConstruct | afterPropertiesSet | @Resource
初识Spring源码 -- initializeBean | @PostConstruct | afterPropertiesSet | @Resource
初识Spring源码 -- 属性填充populateBean | 静态属性注入
初识Spring源码 -- 属性填充populateBean | 静态属性注入
初识Spring源码 -- doResolveDependency | findAutowireCandidates | @Order@Priority调用排序 | @Autowired注入(代码片段