9、Spring之Bean生命周期~依赖注入(总)

9、Spring之Bean生命周期~依赖注入(总)

依赖注入

spring有几种依赖注入方式

从类型角度区分,分两种:手动和自动

手动注入:通过XML中定义Bean时,可手动注入

xml 复制代码
<!-- 通过set方法注入 -->
<bean name="userService" class="com.luban.service.UserService">
	<property name="orderService" ref="orderService"/>
</bean>

<!-- 通过构造器注入 -->
<bean name="userService" class="com.luban.service.UserService">
	<constructor-arg index="0" ref="orderService"/>
</bean>

自动注入

java 复制代码
// xml的形式配置自动注入
<bean id="userService" class="com.luban.service.UserService" autowire="byType"/>

// @Autowired 注解自动注入
@Autowired	

// @Value 注解自动注入 
@Value

// @Inject 注解自动注入 
@Inject

// @Resource 注解自动注入 
@Resource

// @Bean 注解中的autowire属性自动注入 (已废弃)
@Bean(autowire = Autowire.BY_NAME)
@Bean(autowire = Autowire.BY_type)

源码解析

Bean实例化后和初始化之间会进行属性填充,接下来我们将解析属性填充的具体步骤,废话不多说,上代码:

java 复制代码
/**
 * Populate the bean instance in the given BeanWrapper with the property values
 * from the bean definition.
 *
 * @param beanName the name of the bean
 * @param mbd      the bean definition for the bean
 * @param bw       the BeanWrapper with bean instance
 */
@SuppressWarnings("deprecation")  // for postProcessPropertyValues
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 {
			// Skip property population phase for null instance.
			return;
		}
	}

	// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
	// state of the bean before properties are set. This can be used, for example,
	// to support styles of field injection.
	// 实例化之后,属性设置之前
	if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
		for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
			// 执行 InstantiationAwareBeanPostProcessors接口的postProcessAfterInstantiation()方法 根据返回值判断是否跳过属性填充
			if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
				return;
			}
		}
	}

	/**
	 *
	 * 处理spring自带的依赖注入的功能 @Bean(autowire = Autowire.BY_NAME)
	 *
	 * */
	PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
	int resolvedAutowireMode = mbd.getResolvedAutowireMode();
	if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
		// MutablePropertyValues是PropertyValues具体的实现类
		MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
		// Add property values based on autowire by name if applicable.
		if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
			autowireByName(beanName, mbd, bw, newPvs);
		}
		// Add property values based on autowire by type if applicable.
		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;
	if (hasInstAwareBpps) {
		if (pvs == null) {
			pvs = mbd.getPropertyValues();
		}
		for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
			// 这里会调用AutowiredAnnotationBeanPostProcessor的postProcessProperties()方法,会直接给对象中的属性赋值
			// AutowiredAnnotationBeanPostProcessor内部并不会处理pvs,直接返回了
			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);
	}

	// 如果当前Bean中的BeanDefinition中设置了PropertyValues,那么最终将是PropertyValues中的值,覆盖@Autowired
	if (pvs != null) {
		applyPropertyValues(beanName, mbd, bw, pvs);
	}
}

通过上述代码我们可以看到:

  1. 首先,第一个判断是检验Bean对象不是null;
  2. 第二个判断,当一个BeanPostProcessor实现啦InstantiationAwareBeanPostProcessor接口的postProcessAfterInstantiation()方法,并且返回flash时,就不会走属性填充,返回true时,会继续走属性填充;Spring在这一步通过AutowiredAnnotationBeanPostProcessor类的中postProcessMergedBeanDefinition方法寻找@Value和@Autoword的注入点,CommonAnnotationBeanPostProcessor类中的postProcessMergedBeanDefinition方法寻找@Resource的注入点;
  3. 再往下,处理@Bean(autowire = Autowire.BY_NAME)和@Bean(autowire = Autowire.BY_NAME),详情请移步至《Spring之Bean生命周期~依赖注入(1)》;
  4. 再往下,会循环所有实现InstantiationAwareBeanPostProcessor接口的BeanPostProcessor,调用它的postProcessProperties()方法,Spring在这一步通过AutowiredAnnotationBeanPostProcessor类的中postProcessProperties方法给@Value和@Autoword进行注入操作,CommonAnnotationBeanPostProcessor类中的postProcessProperties方法给@Resource的进行注入操作;AutowiredAnnotationBeanPostProcessor类相关依赖注入源码请移步至《Spring之Bean生命周期~依赖注入(2)》,CommonAnnotationBeanPostProcessor类相关依赖注入源码请移步至《Spring之Bean生命周期~依赖注入(3)
  5. 最后,如果当前Bean中的BeanDefinition中设置了PropertyValues,那么最终将是PropertyValues中的值,覆盖@Autowired、@Value、@Resource;
相关推荐
不光头强10 分钟前
SpringBoot 开发第三天 学习内容
java·spring boot·学习
黎雁·泠崖13 分钟前
【魔法森林冒险】12/14 场景系统:5大场景的任务串联
java·开发语言
Vic1010134 分钟前
算法D1-20260212:双指针专题
java·数据结构·算法
大魔王7191 小时前
进程线程和协程一
后端
icebreaker1 小时前
Mokup:构建工具友好的可视化 Mock 工具
前端·javascript·后端
Codiggerworld1 小时前
从字节码到JVM:深入理解Java的“一次编写,到处运行”魔法
java·开发语言·jvm
_codemonster1 小时前
配置Tomcat时为啥要配置Artifacts
java·tomcat·firefox
无心水1 小时前
2025,一路有你!
java·人工智能·分布式·后端·深度学习·架构·2025博客之星
m0_528749001 小时前
C语言错误处理宏两个比较重要的
java·linux·算法