【Spring】深入解析 bean 的属性填充 一 autowireByName autowireByType

本文详细探讨了Spring框架中bean属性填充的过程,包括byName和byType两种自动依赖注入方式。核心关注点在于@Autowired注解的属性填充,涉及AbstractAutowireCapableBeanFactory的doCreateBean、populateBean方法以及AutowiredAnnotationBeanPostProcessor的postProcessProperties方法。通过源码分析,揭示了属性注入的内部机制,如BeanDefinition的解析、InstantiationAwareBeanPostProcessor的作用以及AutowiredAnnotationBeanPostProcessor如何处理@Autowired注解的属性注入。此外,还介绍了InstantiationAwareBeanPostProcessor如何辅助完成属性填充,特别是AutowiredFieldElement#inject方法的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

@Configuration
public class Config {

    @Bean
    public BasicPOJO a() {

        return new BasicPOJO("a");
    }

    @Bean
    public BasicPOJO b() {

        return new BasicPOJO("b");
    }

    @Bean
    public GenericPOJO<Integer, Integer> integerGenericPOJO() {

        return new GenericPOJO<Integer, Integer>("integer");
    }

    @Bean
    public GenericPOJO<String, String> stringGenericPOJO() {

        return new GenericPOJO<String, String>("string");
    }

    @Component
    public class Container {

		// 注入上述实例 a
        @Autowired
        BasicPOJO a;

		// 基于 Value 注解解析 SpEL 表达式,也可以注入 bean实例
		@Value("#{a}")
        BasicPOJO aValue;

		// 基于 Qualifier 注解解析注入实例 b
        @Autowired
        @Qualifier("b")
        BasicPOJO basicPOJO;

		// Qualifier 作为元注解解析注入实例 b
		@Autowired
        @MyQualifier("b")
        BasicPOJO basicPOJO2;

		// 以 name -> 实例 形式注入所有 BasicPOJO 实例
        @Autowired
        Map<String, BasicPOJO> map;

		// 注入指定泛型实例
        @Autowired
        GenericPOJO<Integer, Integer> i;

        GenericPOJO<String, String> s;

		// 基于方法注入指定泛型实例
        @Autowired
        public void setStringGenericPOJO(GenericPOJO<String, String> stringGenericPOJO) {

            this.s = stringGenericPOJO;
        }
    }
}

如上配置类,组件 Container 的所有属性是可以被完整填充的,这就是我们所谓的 IOCbean实例 的属性填充通常发生在实例化 Instantiation 完成后(除非是指定了 AUTOWIRE_CONSTRUCTOR 或者 @Bean 注册的实例),本文分多个章节了解如下相关:

  • 属性填充的时机及上下文
  • byName byType 自动依赖注入
  • 核心:基于 @Autowired 注解的属性填充,主要解读 AutowiredAnnotationBeanPostProcessor 类相关,其中涉及的诸多细节,比如上述实例的属性如何符合我们预期被注入

AbstractAutowireCapableBeanFactory#doCreateBean

	protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {

		/**
		 * 构造(或从缓存获取)对应 bean实例 的 BeanWrapper
		 */
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		Object bean = instanceWrapper.getWrappedInstance();
		Class<?> beanType = instanceWrapper.getWrappedClass();
		if (beanType != NullBean.class) {
			mbd.resolvedTargetType = beanType;
		}

		/**
		 * 实例创建完成后,调用所有
		 * 		MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition
		 * 		对目标 bean实例 的 BeanDefinition 进行后处理
		 * 在这个过程中,AutowiredAnnotationBeanPostProcessor 会把
		 * 		所有需要注入的元素(属性、方法)收集起来
		 */
		synchronized (mbd.postProcessingLock) {
			if (!mbd.postProcessed) {
				try {
					applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
				}
				catch (Throwable ex) {
					
				}
				mbd.postProcessed = true;
			}
		}

		// 对于 循环依赖 的单例此处现提前暴露实例给单例工厂(二级缓存)
		// ...

		Object exposedObject = bean;
		try {
			// 属性填充
			populateBean(beanName, mbd, instanceWrapper);

			// 初始化
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		}
		catch (Throwable ex) {
			
		}

		// ...

		return exposedObject;
	}

基于容器中的 BeanDefinition 创建 bean实例 时,最终委托给方法 AbstractAutowireCapableBeanFactory#doCreateBean,主要流程如下:

  • 基于 createBeanInstance 方法创建对应的 BeanWrapper,该过程中对于指定了依赖注入模式为 构造方法注入(AUTOWIRE_CONSTRUCTOR) 或通过工厂方法(比如基于 @Bean 注册)创建的实例会以 构造方法自动依赖注入 的形式进行一次属性填充,此处不做深入了解
  • 执行所有 MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition,其中 AutowiredAnnotationBeanPostProcessor 会收集所有需要进行注入的元素,即所有被 @Autowired @Value 注解的属性与方法
  • 基于 populateBean 方法进行属性填充
  • initializeBean 方法执行初始化相关

上述诸多细节在之前的 BeanFactory 相关文章都有解读,可前往对应专栏参考,本文重点关注 populateBean

populateBean

	protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
		
		// ...

		/**
		 * 此处是调用所有的 InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation
		 * 		但凡有返回 false,此处就 return 不继续注入了,目前的默认实现都是 true
		 */
		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
				if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
					return;
				}
			}
		}

		// 从 BeanDefinition 获取 PropertyValues
		PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

		/**
		 * 自动注入模式
		 * AUTOWIRE_BY_NAME:根据名称注入
		 * AUTOWIRE_BY_TYPE:根据类型注入
		 * 一般情况 resolvedAutowireMode == AUTOWIRE_NO
		 */
		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);

		PropertyDescriptor[] filteredPds = null;
		/**
		 * 如果存在 InstantiationAwareBeanPostProcessor
		 * 则执行所有 InstantiationAwareBeanPostProcessor#postProcessProperties
		 * 		辅助完成属性填充,诸如基于 @Autowired 等注解的属性注入就发生在此处
		 */
		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 (pvs != null) {
			applyPropertyValues(beanName, mbd, bw, pvs);
		}
	}

属性填充的核心方法,主要流程如下:

  • 在进行属性填充之前,执行所有 InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation 方法,此处如果有返回 false,则不再进行下去,目前所有的实现都是返回 true
  • 基于 BeanDefinition 获取 PropertyValues,用于后续基于 BeanWrapper 进行属性赋值
  • 基于 AutowireMode 进行 byName byType 依赖自动注入,下文会再解读
  • 执行所有 InstantiationAwareBeanPostProcessor#postProcessProperties,其中本文重点关注的是 AutowiredAnnotationBeanPostProcessor:基于 @Autowired @Value 注解的属性注入,下文会再解读
  • applyPropertyValues 方法是基于 BeanDefinition.propertyValues 的属性赋值,比如我们自行指定或基于 xml 驱动时的 <property> 标签指定

autowireByName

	protected void autowireByName(
			String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {

		/**
		 * 收集所有需要注入的属性名称
		 */
		String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
		for (String propertyName : propertyNames) {
			if (containsBean(propertyName)) {
				// 对应的属性从容器取出后放到 pvs 中
				Object bean = getBean(propertyName);
				pvs.add(propertyName, bean);
				registerDependentBean(propertyName, beanName);
				// ...
			}
			else {
				// ...
			}
		}
	}

byName 的属性注入:

  • 收集需要自动注入的依赖属性
  • byName 注入的逻辑基于方法 getBean(name)

autowireByType

	protected void autowireByType(
			String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {

		// ...

		Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
		// 收集所有需要填充的 propertyName
		String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
		for (String propertyName : propertyNames) {
			try {
				PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
				if (Object.class != pd.getPropertyType()) {
					MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
					boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered);
					
					// 构造对应的 DependencyDescriptor
					DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
					
					// 基于 resolveDependency 方法从容器中获取对应 bean
					Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
					if (autowiredArgument != null) {
						pvs.add(propertyName, autowiredArgument);
					}
					
					// 注册依赖关系
					for (String autowiredBeanName : autowiredBeanNames) {
						registerDependentBean(autowiredBeanName, beanName);
					}
					autowiredBeanNames.clear();
				}
			}
			catch (BeansException ex) {
				
			}
		}
	}

byType 的属性注入:

  • 整体思路与 byName 注入差不多,区别在于此处基于 resolveDependency 方法获取对应 bean
  • resolveDependency 是解析注入的核心方法,由 AutowireCapableBeanFactory 接口定义,最终实现在 DefaultListableBeanFactory 中,下文中 AutowiredAnnotationBeanPostProcessor 也会用到此方法,到时会详细分析该方法

一般的,我们并不会特别的指定对应 bean 实例为 byName byType 诸如,即默认情况下都是基于注解进行属性注入,接下来重点解读基于后处理器的属性注入,比如 AutowiredAnnotationBeanPostProcessor

AutowiredAnnotationBeanPostProcessor#postProcessProperties

	@Override
	public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
		/**
		 * 获取所有待注入的元素:
		 * 这些元素是在 postProcessMergedBeanDefinition 阶段被收集起来的
		 */
		InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);

		/**
		 * 进行元素注入
		 */
		try {
			metadata.inject(bean, beanName, pvs);
		}
		catch (BeanCreationException ex) {
			
		}
		return pvs;
	}

	-------------- InjectionMetadata#inject ---------------

	/**
	 * 执行所有 InjectedElement#inject
	 * 属性:AutowiredFieldElement
	 * 方法:AutowiredMethodElement
	 */
	public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
		Collection<InjectedElement> checkedElements = this.checkedElements;
		Collection<InjectedElement> elementsToIterate =
				(checkedElements != null ? checkedElements : this.injectedElements);
		if (!elementsToIterate.isEmpty()) {
			for (InjectedElement element : elementsToIterate) {
				element.inject(target, beanName, pvs);
			}
		}
	}
  • postProcessMergedBeanDefinition 阶段(发生在 bean实例对象 刚被创建完后),AutowiredAnnotationBeanPostProcessor 会收集所有需要被注入的属性和方法(被 @Autowired @Value 注解修饰)
  • 对应属性被封装成 AutowiredFieldElement,对应方法被封装成 AutowiredMethodElement
  • 在该阶段,会执行上述元素的 inject 方法进行注入,后续我们会重点解读 InjectedElement#inject 方法
  • postProcessPropertyValues 方法已被标注 @Deprecated,在后续版本会移除,此处只是做了兜底

总结

本章节,我们对整个属性注入的链路做了梳理,同时解读了 byName byType 属性填充的原理,其中 byType 注入委托的核心方法 resolveDependency 我们会在下章重点解读

之后在 postProcessProperties 阶段的属性注入是本文的核心,核心逻辑收口到 InjectedElement#inject,其中涉及的细节也很多,会在下章详细解读

参考

【小家Spring】细说Spring IOC容器的自动装配(@Autowired),以及Spring4.0新特性之【泛型依赖注入】的源码级解析

下一篇:【Spring】深入解析 bean 的属性填充 二 AutowiredFieldElement#inject

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值