当前位置: 首页 > news >正文

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个重写,分别是AutowiredFieldElementAutowiredMethodElement,相对应的是注解在属性上和注解在方法上。
在这里插入图片描述
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

匹配逻辑

  1. 根据type找到所有beanName
  2. 遍历beanName筛选 SimpleAutowireCandidateResolver->GenericTypeAwareAutowireCandidateResolve->QualifierAnnotationAutowireCandidateResolver
  3. 为空考虑回退匹配
  4. 还是为空考虑匹配自己

大部分场景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注入,属性注入,构造器注入

相关文章:

  • 【Note2】macvlan,sol
  • 01 | Msyql系统架构
  • new bing的chatGPT如何解析英文论文pdf
  • Java - 配置中心初体验
  • 10个杀手级应用的Python自动化脚本
  • 接口的定义和实现
  • [Java Web]JSP进阶
  • CSS - 扫盲
  • 学习 Python 之 Pygame 开发魂斗罗(十一)
  • 蓝桥杯刷题冲刺 | 倒计时18天
  • 蚁群算法c++
  • 【粉丝投稿】上海某大厂的面试题,岗位是测开(25K*16)
  • 【文心一言】什么是文心一言,如何获得内测和使用方法。
  • 到底什么是线程?线程与进程有哪些区别?
  • 蓝桥杯刷题冲刺 | 倒计时19天
  • vue面试题(day04)
  • 高数重点总结
  • Python中 5个非常有用的单行代码
  • 基于EB工具的TC3xx_MCAL配置开发04_ADC模块软件触发Demo配置
  • 微前端(无界)