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

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

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

  • 依赖注入
    • spring有几种依赖注入方式
    • 源码解析

依赖注入

spring有几种依赖注入方式

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

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

<!-- 通过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>

自动注入

// 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实例化后和初始化之间会进行属性填充,接下来我们将解析属性填充的具体步骤,废话不多说,上代码:

/*** 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中的值,覆盖@Autowiredif (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;

相关文章:

  • python入门基础知识(错误和异常)
  • 兴顺物流管理系统的设计
  • 从开源EPR产品Odoo学习
  • Java之Hutool/Guava/Apache Commons工具包项目实践
  • Node.js 渲染三维模型并导出为图片
  • 后仿真中的 《specify/endspecify block》之(5)使用specify进行时序仿真
  • 【区分vue2和vue3下的element UI Descriptions 描述列表组件,分别详细介绍属性,事件,方法如何使用,并举例】
  • GPT-4o一夜被赶超,Claude 3.5一夜封王|快手可灵大模型推出图生视频功能|“纯血”鸿蒙大战苹果AI|智谱AI“钱途”黯淡|月之暗面被曝进军美国
  • 4、MFC:菜单栏、工具栏与状态栏
  • CompletableFuture 基本用法
  • 实战|YOLOv10 自定义目标检测
  • 数学建模 —— 查找数据
  • Tomcat基础详解
  • 【MATLAB】语法
  • atcoder abc 358
  • 「前端」从UglifyJSPlugin强制开启css压缩探究webpack插件运行机制
  • 4. 路由到控制器 - Laravel从零开始教程
  • angular学习第一篇-----环境搭建
  • express.js的介绍及使用
  • GitUp, 你不可错过的秀外慧中的git工具
  • Java 网络编程(2):UDP 的使用
  • Java,console输出实时的转向GUI textbox
  • Java到底能干嘛?
  • Js基础——数据类型之Null和Undefined
  • Vue全家桶实现一个Web App
  • win10下安装mysql5.7
  • 技术胖1-4季视频复习— (看视频笔记)
  • 面试题:给你个id,去拿到name,多叉树遍历
  • 强力优化Rancher k8s中国区的使用体验
  • # Redis 入门到精通(九)-- 主从复制(1)
  • #Z0458. 树的中心2
  • #每日一题合集#牛客JZ23-JZ33
  • #图像处理
  • #周末课堂# 【Linux + JVM + Mysql高级性能优化班】(火热报名中~~~)
  • (02)Cartographer源码无死角解析-(03) 新数据运行与地图保存、加载地图启动仅定位模式
  • (3)Dubbo启动时qos-server can not bind localhost22222错误解决
  • (BAT向)Java岗常问高频面试汇总:MyBatis 微服务 Spring 分布式 MySQL等(1)
  • (笔试题)合法字符串
  • (顶刊)一个基于分类代理模型的超多目标优化算法
  • (附源码)php投票系统 毕业设计 121500
  • (论文阅读11/100)Fast R-CNN
  • (十七)、Mac 安装k8s
  • (四)事件系统
  • (学习日记)2024.03.25:UCOSIII第二十二节:系统启动流程详解
  • (一)utf8mb4_general_ci 和 utf8mb4_unicode_ci 适用排序和比较规则场景
  • (原+转)Ubuntu16.04软件中心闪退及wifi消失
  • .bashrc在哪里,alias妙用
  • .NET 4 并行(多核)“.NET研究”编程系列之二 从Task开始
  • .NET Core SkiaSharp 替代 System.Drawing.Common 的一些用法
  • .NET 发展历程
  • .NET程序员迈向卓越的必由之路
  • .NET序列化 serializable,反序列化
  • .secret勒索病毒数据恢复|金蝶、用友、管家婆、OA、速达、ERP等软件数据库恢复
  • /ThinkPHP/Library/Think/Storage/Driver/File.class.php  LINE: 48
  • @Service注解让spring找到你的Service bean