初识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注入(代码片段