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;
相关推荐
Wzx19801213 分钟前
go聊天室
开发语言·后端·golang
chenyuhao202440 分钟前
MySQL索引特性
开发语言·数据库·c++·后端·mysql
oouy1 小时前
《Java泛型:给你的代码装上“快递分拣系统”,再也不会拆出一双鞋!》
后端
Python私教1 小时前
别再瞎折腾 LangChain 了:从 0 到 1 搭建 RAG 知识库的架构决策实录
后端
微学AI1 小时前
openGauss在AI时代的向量数据库应用实践与技术演进深度解析
后端
踏浪无痕1 小时前
手写Spring事务框架:200行代码揭开@Transactional的神秘面纱( 附完整源代码)
spring boot·spring·spring cloud
踏浪无痕1 小时前
5个测试用例带你彻底理解Spring事务传播行为( 附完整源代码)
spring boot·spring·spring cloud
前端伪大叔1 小时前
第29篇:99% 的量化新手死在挂单上:Freqtrade 隐藏技能揭秘
后端·python·github
白衣鸽子1 小时前
【基础数据篇】数据格式化妆师:Formatter模式
后端·设计模式
雨中飘荡的记忆1 小时前
财务对账系统设计与实现
java