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;
相关推荐
程序猿DD3 小时前
OctaFuse Gateway 2.15.0:MCP 聚合、向量 Embeddings 与官方目录同步
后端·agent
蛋蛋的就会顺顺的6 小时前
hot100 p0——栈,贪心算法,动态规划
java·前端·javascript·算法·leetcode·力扣
余槐i6 小时前
PostgreSQL 函数索引报错 must be immutable:3种绕法与代价
数据库·后端·sql·postgresql·性能优化
需要8266 小时前
Spring Bean 生命周期:从实例化到销毁的完整钩子
java·后端·spring
小 黄 鸡6 小时前
HashMap 面试必会知识点详解(JDK 8)
java·面试·职场和发展
凤山老林7 小时前
Spring Boot 接入国密 SM2/SM3/SM4 的一些实践记录
spring boot·后端·python
伯恩bourne8 小时前
Spring Boot Bean 注册的两种方式:@Component 家族 vs @Configuration + @Bean
java·spring boot·后端
张彦峰ZYF8 小时前
停顿短不等于延迟低:G1、ZGC 与低延迟服务的目标分野、代价账本与选型标定
后端·回收暂停、应用停止总时长·到达安全点、分配停滞·屏障吃吞吐、并发线程吃核心·并发窗口吃堆余量·分区式靠挑回收集兑现目标·染色指针式不支持压缩引用
silvamux_8 小时前
curl 测试 OpenAI 兼容 API 的完整流程
java·人工智能·缓存·ai·oneapi
pride.li9 小时前
第03章 Python 教程-基础语法:注释与变量
服务器·前端·后端·python·算法·计算机视觉