SpringBoot源码解析 -- @Value,@Autowired实现原理

2,527 阅读4分钟

SpringBoot深入理解 -- @AliasFor注解的作用
SpringBoot源码解析 -- SpringBoot启动过程
SpringBoot源码解析 -- AutoConfigure的实现原理
SpringBoot源码解析 -- @ComponentScan的实现原理
SpringBoot源码解析 -- @Value,@Autowired实现原理
SpringBoot源码解析 -- Tomcat,SpringMVC启动
SpringBoot源码解析 -- Logging,Environment启动

前面解析@ComponentScan实现原理的文章说了,Spring如何扫描@Component注解的Bean,但扫描的Bean如何注入属性呢?
我们都知道该功能主要使用@Value,@Autowired注解完成,这篇文章主要解析Spring中@Value,@Autowired实现原理。
源码分析基于spring boot 2.1

前面解析Spring注入属性过程的文章中,说过AbstractAutowireCapableBeanFactory#populateBean方法负责注入bean的属性,其实@Value,@Autowired等注解也是在该方法处理。

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
	...
	PropertyDescriptor[] filteredPds = null;
	if (hasInstAwareBpps) {
		if (pvs == null) {
			pvs = mbd.getPropertyValues();
		}
		for (BeanPostProcessor bp : getBeanPostProcessors()) {
			if (bp instanceof InstantiationAwareBeanPostProcessor) {
				InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
				// #1
				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;
			}
		}
	}
	...
}

#1 调用InstantiationAwareBeanPostProcessor#postProcessProperties扩展方法,这里处理@Value,@Autowired等注解。

在解析SpringBoot启动过程的文章中,说过了AutowiredAnnotationBeanPostProcessor负责处理@Value,@Autowired等注解。
(AutowiredAnnotationBeanPostProcessor是InstantiationAwareBeanPostProcessor的实现类) AutowiredAnnotationBeanPostProcessor#postProcessProperties

public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
	// #1
	InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);	
	try {
		// #2
		metadata.inject(bean, beanName, pvs);	
	}
	...
	return pvs;
}

#1 获取Class中关于属性注入相关注解的元数据
#2 完成属性注入操作

AutowiredAnnotationBeanPostProcessor#findAutowiringMetadata -> buildAutowiringMetadata

	private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
		LinkedList<InjectionMetadata.InjectedElement> elements = new LinkedList<InjectionMetadata.InjectedElement>();
		Class<?> targetClass = clazz;

		do {
			final LinkedList<InjectionMetadata.InjectedElement> currElements =
					new LinkedList<InjectionMetadata.InjectedElement>();

			ReflectionUtils.doWithLocalFields(targetClass, new ReflectionUtils.FieldCallback() {
				@Override
				public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
					// #1
					AnnotationAttributes ann = findAutowiredAnnotation(field);
					if (ann != null) {
						if (Modifier.isStatic(field.getModifiers())) {
							if (logger.isWarnEnabled()) {
								logger.warn("Autowired annotation is not supported on static fields: " + field);
							}
							return;
						}
						boolean required = determineRequiredStatus(ann);
						currElements.add(new AutowiredFieldElement(field, required));
					}
				}
			});

			...	// #2

			elements.addAll(0, currElements);
			targetClass = targetClass.getSuperclass();
		}
		while (targetClass != null && targetClass != Object.class);

		return new InjectionMetadata(clazz, elements);
	}

#1 查找field是否有@Autowired,@Value等注解
#2 查找method是否有@Autowired,@Value等注解

InjectionMetadata#inject方法遍历所有的InjectedElement,调用AutowiredMethodElement,AutowiredFieldElement的inject方法,这里只关注AutowiredFieldElement#inject InjectionMetadata#inject -> AutowiredFieldElement#inject

protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
	Field field = (Field) this.member;
	Object value;
	if (this.cached) {
		value = resolvedCachedArgument(beanName, this.cachedFieldValue);
	}
	else {
		DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
		desc.setContainingClass(bean.getClass());
		Set<String> autowiredBeanNames = new LinkedHashSet<String>(1);
		TypeConverter typeConverter = beanFactory.getTypeConverter();
		try {
			// #1
			value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);	
		}
		catch (BeansException ex) {
			throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
		}
		...
	}
	if (value != null) {
		// #2
		ReflectionUtils.makeAccessible(field);	
		field.set(bean, value);
	}
}

#1 根据注解元数据,解析属性值
#2 将解析的结果值注入到bean

DefaultListableBeanFactory#resolveDependency -> DefaultListableBeanFactory#doResolveDependency

public Object doResolveDependency(DependencyDescriptor descriptor, String beanName,
		Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {

	InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
	try {
		Object shortcut = descriptor.resolveShortcut(this);
		if (shortcut != null) {
			return shortcut;
		}

		Class<?> type = descriptor.getDependencyType();
		// #1
		Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);	
		if (value != null) {
			if (value instanceof String) {
				// #2
				String strVal = resolveEmbeddedValue((String) value);	
				BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null);
				value = evaluateBeanDefinitionString(strVal, bd);
			}
			//#3
			TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());	
			return (descriptor.getField() != null ?
					converter.convertIfNecessary(value, type, descriptor.getField()) :
					converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
		}

		// #4
		Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);	
		if (multipleBeans != null) {
			return multipleBeans;
		}

		// #5
		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;

		// #6
		if (matchingBeans.size() > 1) {
			autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);	
			if (autowiredBeanName == null) {
				if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
					return descriptor.resolveNotUnique(type, matchingBeans);
				}
				else {
					return null;
				}
			}
			instanceCandidate = matchingBeans.get(autowiredBeanName);
		}
		else {
			Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
			autowiredBeanName = entry.getKey();
			instanceCandidate = entry.getValue();
		}

		if (autowiredBeanNames != null) {
			autowiredBeanNames.add(autowiredBeanName);
		}
		return (instanceCandidate instanceof Class ?
				descriptor.resolveCandidate(autowiredBeanName, type, this) : instanceCandidate);
	}
	finally {
		ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
	}
}

#1 如果存在@Value注解,获取注解的value值
#2 解析@Value注解的值,如果这里使用占位符引用了配置文件,默认使用PropertyPlaceholderConfigurer#PlaceholderResolvingStringValueResolver解析配置文件中的值。
PropertyPlaceholderConfigurer是一个常用的BeanFactoryPostProcessor,它可以在Spring启动时,将Bean属性配置的占位符解析为配置属性的值
#3 默认使用SimpleTypeConverter将配置值转化为属性要求的类型(例如属性为int类型,则需要将String转换为int类型)
这里最终也会复用TypeConverterDelegate#convertIfNecessary方法。
#4 解析数组、list、map等类型的依赖,使用对应的TypeConverter处理
#5 处理@Autowire,找到候选的bean
#6 存在多个候选的bean,spring要按优先级决定用哪个。

DefaultListableBeanFactory#findAutowireCandidates

protected Map<String, Object> findAutowireCandidates(
		String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {

	// #1
	String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
			this, requiredType, true, descriptor.isEager());	
	Map<String, Object> result = new LinkedHashMap<String, Object>(candidateNames.length);
	// #2
	for (Class<?> autowiringType : this.resolvableDependencies.keySet()) {	
		if (autowiringType.isAssignableFrom(requiredType)) {
			Object autowiringValue = this.resolvableDependencies.get(autowiringType);
			autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);
			if (requiredType.isInstance(autowiringValue)) {
				result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);
				break;
			}
		}
	}
	//#3
	for (String candidate : candidateNames) {
		if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {	
			addCandidateEntry(result, candidate, descriptor, requiredType);
		}
	}
	...
	return result;
}

#1 按类型查找spring上下文中所有的bean
#2 从当前已存在的依赖关系中查找
#3 遍历#1步骤中找到的bean,如果满足Autowire要求,添加到结果
这里检查候选类的类型是否匹配,是否满足@Qualifier的要求,不继续深入,有兴趣的同学自行阅读源码。

下面来看一下@Autowired存在多个候选bean时,Spring如何处理。 DefaultListableBeanFactory#determineAutowireCandidate

protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
	Class<?> requiredType = descriptor.getDependencyType();
	// #1
	String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
	if (primaryCandidate != null) {
		return primaryCandidate;
	}
	// #2
	String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
	if (priorityCandidate != null) {
		return priorityCandidate;
	}
	// #3
	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;
}

1 查找候选bean中是否有@Primary标注,如果有,则使用该bean。
局限性,只能在一个候选bean上标注@Primary。
2 如果候选bean是通过在Class上使用@Component,@Service,@Controller标注创建的,并且使用了@Priority标注了优先级数值, 则取优先级数值最小的bean(优先级数值越小,优先级越高)。
标注了@Priority的候选bean比所有没标注@Priority的候选bean优先级高。
局限性,不能用于@Bean标注的方法生成的bean。
3 如果字段名和beanName或bean别名相同,则返回该bean

使用@Autowired注解时,要考虑存在多个相同类型的bean场景,最好字段名和目标beanName保持一致或使用@Qualifier注解。

如果您觉得本文不错,欢迎关注我的微信公众号,您的关注是我坚持的动力!