Spring5源码5-Bean生命周期后置处理器

SpringIOC中Bean的生命周期以及各种PostProcessor后置处理器的执行时机 一.SpringIOC大致流程可以总结为 读取解析配置文件 -> 组装bean定义放到Map -> 根据bean定义依次创建对象 -> 把对象都放到map 这四个大步骤 二.Spring有三种生命周期增强器 BeanFactoryPostProcessor Bean工厂后置处理器,可以对工厂进行增强 BeanPostProcessor Bean的后置处理器,对Bean的实例化前后,初始化前后进行干预。 InitalizingBean Bean完全初始化后可以进行一波处理... 阅读详情

本文主要讲解 Bean的生命周期后置处理器,关于bean创建对象流程我们后面在讲。主要说明三种生命周期增强器:

  • BeanFactoryPostProcessor:BeanFactory 后置处理器

    • BeanDefinitionRegistryPostProcessor:bean定义注册后置处理器
    • BeanFactoryPostProcessor
  • BeanPostProcessor:Bean后置处理器

    • BeanPostProcessor
    • MergedBeanDefinitionPostProcessor
    • SmartInstantiationAwareBeanPostProcessor
    • InstantiationAwareBeanPostProcessor
  • InitializingBean

  • DisposableBean (销毁的方案我们暂时不做说明)

1. 简介

1.1 什么是 BeanPostProcessor

BeanPostProcessor 是 Spring提供给我们的一个非常重要的扩展接口,并且Spring内部的很多功能也是通过 BeanPostProcessor 来完成的(目前看到最典型的就是 AnnotationAwareAspectJAutoProxyCreator 的 注入)。

1.2 BeanPostProcessor 的种类

BeanPostProcessor 在Spring 中的子类非常多(idea 显是有46个),比如

  • InstantiationAwareBeanPostProcessorAdapter : 在Spring 的bean加载过程中起了非常重要的作用
  • AnnotationAwareAspectJAutoProxyCreator : bean 创建过程中的 属性注入时起作用
  • AspectJAwareAdvisorAutoProxyCreator : Aspect 的 AOP 功能实现也全仰仗BeanPostProcessor 的特性。

1.3 创建时机

BeanFactoryPostProcessor:在 Spring 启动时对BeanDefinition 的创建 进行干预处理。

BeanPostProcessor:一是Bean对应的BeanDefinition 的创建。二是Bean 实例的创建。因为在 Spring容器中,Bean的创建并非仅仅通过反射创建就结束了,在创建过程中,需要考虑到Bean针对Spring容器中的一些属性,所以BeanDefinition 中不仅仅包含了 Bean Class 文件信息,还包含了 当前Bean在Spring容器中的一些属性,比如在容器中的作用域、是否懒加载、别名等信息。当Bean 进行实例化创建时需要依赖于对应的BeanDefinition 提供对应的信息。。

而由于 BeanPostProcessor 是参与了 Bean 创建过程。所以其创建一定在普通 Bean 之前。实际上 BeanPostProcessor 的创建时在 Spring 启动时容器刷新的时候。

BeanPostProcessor 的 BeanDefinition 创建时机和普通 Bean没有区别,都是在Spring 启动时的BeanFactoryPostProcessor 中完成(确切的说是 ConfigurationClassPostProcessor 中完成)。

而BeanPostProcessor 的实例创建要优先于普通bean创建,Spring启动过程中会调用AbstractApplicationContext#registerBeanPostProcessors 方法。 在这个方法中,Spring 会从容器中获取到所有BeanPostProcessor 类型的beanName, 通过 beanFactory.getBean 方法获取到对应实例,进行排序后注册到 BeanFactory.beanPostProcessors 属性中.当容器需要执行 BeanPostProcessor 方法时可以直接从 beanPostProcessors 中获取即可。

2. 案例

分别定义几个测试类,实现bean的后置处理器:

BeanDefinitionRegistryPostProcessor:

/**
 * BeanFactory的后置处理器  , PriorityOrdered, Ordered
 */
@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
   public MyBeanDefinitionRegistryPostProcessor(){
      System.out.println("MyBeanDefinitionRegistryPostProcessor");
   }

   @Override  //紧接着执行
   public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
      System.out.println("MyBeanDefinitionRegistryPostProcessor....postProcessBeanFactory...");
   }

   @Override  //先执行的
   public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
      System.out.println("MyBeanDefinitionRegistryPostProcessor...postProcessBeanDefinitionRegistry...");
      //增强bean定义信息的注册中心,比如自己注册组件

   }
}

BeanFactoryPostProcessor:

/**
 * BeanFactory的后置处理器
 */
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

   public MyBeanFactoryPostProcessor(){
      System.out.println("MyBeanFactoryPostProcessor...");
   }

   @Override
   public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
      System.out.println("BeanFactoryPostProcessor....postProcessBeanFactory==>"+beanFactory);
   }
}

BeanPostProcessor:

/**
 * Bean组件的 PostProcessor;
 */
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {

   public MyBeanPostProcessor(){
      System.out.println("MyBeanPostProcessor...");
   }

   public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
      System.out.println("MyBeanPostProcessor...postProcessAfterInitialization..."+bean+"==>"+beanName);
      return bean;
   }

   public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
      System.out.println("MyBeanPostProcessor...postProcessBeforeInitialization..."+bean+"==>"+beanName);
      return bean; // new Object();
   }
}

InstantiationAwareBeanPostProcessor:

@Component
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {

   public MyInstantiationAwareBeanPostProcessor(){
      System.out.println("MyInstantiationAwareBeanPostProcessor...");
   }

   //初始化之前进行后置处理,Spring留给我们给这个组件创建对象的回调。
   public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
      System.out.println("MyInstantiationAwareBeanPostProcessor...postProcessBeforeInstantiation=>"+beanClass+"--"+beanName);
      //if(class.isAssFrom(Cat.class)){return new Dog()}
      //如果我们自己创建了对象返回。Spring则不会帮我们创建对象,用我们自己创建的对象? 我们创建的这个对象,Spring会保存单实例?还是每次getBean都调到我们这里创建一个新的?
      return null;
   }

   // 是否让剩下的后置处理器对bean继续进行处理
   public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
      //提前改变一些Spring不管的bean里面的属性
      System.out.println("MyInstantiationAwareBeanPostProcessor...postProcessAfterInstantiation=>"+bean+"--"+beanName);
      return true; //返回false则bean的赋值全部结束
   }
   //解析自定义注解进行属性值注入;pvs 封装了所有的属性信息。
   public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
         throws BeansException { //@GuiguValue();redis
      System.out.println("MyInstantiationAwareBeanPostProcessor...postProcessProperties=>"+bean+"--"+beanName);
      return null;
   }

// public PropertyValues postProcessPropertyValues(
//       PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
//    System.out.println("MyInstantiationAwareBeanPostProcessor...postProcessProperties");
//    return pvs;
// }
}

MergedBeanDefinitionPostProcessor:

@Component
public class MyMergedBeanDefinitionPostProcessor implements MergedBeanDefinitionPostProcessor {

   public MyMergedBeanDefinitionPostProcessor(){
      System.out.println("MyMergedBeanDefinitionPostProcessor...");
   }

   @Override
   public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
      System.out.println("MyMergedBeanDefinitionPostProcessor...postProcessBeforeInitialization...=>"+bean+"--"+beanName);
      return bean; //null
   }

   @Override
   public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
      System.out.println("MyMergedBeanDefinitionPostProcessor...postProcessAfterInitialization..=>"+bean+"--"+beanName);
      return null;
   }

   @Override
   public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
      System.out.println("MyMergedBeanDefinitionPostProcessor...postProcessMergedBeanDefinition..=>"+beanName+"--"+beanType+"---"+beanDefinition);
   }

   @Override
   public void resetBeanDefinition(String beanName) {
      System.out.println("MyMergedBeanDefinitionPostProcessor...resetBeanDefinition.."+beanName);

   }
}

SmartInstantiationAwareBeanPostProcessor:

@Component   //bean进行代理增强期间进行使用
public class MySmartInstantiationAwareBeanPostProcessor implements SmartInstantiationAwareBeanPostProcessor {

   public MySmartInstantiationAwareBeanPostProcessor(){
      System.out.println("MySmartInstantiationAwareBeanPostProcessor...");
   }

   //预测bean的类型,最后一次改变组件类型。
   public Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException {
      System.out.println("MySmartInstantiationAwareBeanPostProcessor...predictBeanType=>"+beanClass+"--"+beanName);
      return null;
   }

    //返回我们要使用的构造器候选列表
   public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException {
      System.out.println("MySmartInstantiationAwareBeanPostProcessor...determineCandidateConstructors=>"+beanClass+"--"+beanName);
      //返回一个我们指定的构造器
      return null;
   }

     //返回早期的bean引用,定义三级缓存中的bean信息
   public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
      System.out.println("MySmartInstantiationAwareBeanPostProcessor...getEarlyBeanReference=>"+bean+"--"+beanName);

      return bean; //
   }

}

InitializingBean:

@Component
public class CatInitializingBean implements InitializingBean {

   public CatInitializingBean(){
      System.out.println("cat被创建了...");
   }

   private String name;


   @Value("${JAVA_HOME}") //自动赋值功能
   public void setName(String name) {
      System.out.println("cat....setName正在赋值调用....");
      this.name = name;
   }
   //注解怎么定义这个是初始化方法?
   public String getName() {
      return name;
   }

   @Override
   public void afterPropertiesSet() throws Exception {
      System.out.println("CatInitializingBean..afterPropertiesSet...");
   }

   @Autowired
   private void init() {
      System.out.println("CatInitializingBean init....");
   }

}

debug打点:在每个构造器和方法上都打上 断点,主要看看每个方法的执行时机是什么时候?

3. 源码分析

入口还是: org.springframework.context.support.AbstractApplicationContext#refresh:

// 容器刷新的十二大步骤
@Override
public void refresh() throws BeansException, IllegalStateException {
   synchronized (this.startupShutdownMonitor) {
      // 容器启动的状态
      StartupStep contextRefresh = this.applicationStartup.star
SAP Script表单开发中ABAP preform方法的实战应用与调试技巧 本文深入探讨了在SAP Script表单开发中调用ABAP程序(preform方法)的实战应用与调试技巧。通过一个获取供应商版本名称的实例,详细讲解了如何在SE71中嵌入PERFORM指令、编写ABAP子程序进行数据查询与处理,并重点介绍了使用SAP Script Debugger进行高效调试的方法,帮助开发者灵活扩展表单功能,实现复杂业务逻辑。 阅读详情

相关推荐

C语言实现贪吃蛇小游戏!(超简单详细)详细思路+源码分享

我们的今天的目标就是:用C语言来实现一个贪吃蛇项目,也不用太复杂,初学者能看懂就行!

致力于C语言C++知识分享! 1万+

共享单车数据分析与需求预测项目

除了自行车共享系统的有趣的实际应用之外,这些系统生成的数据特征使它们成为研究的有吸引力的对象。由于这些系统在交通、环境和健康问题中的重要作用,它们引起了极大的关注。Huber 回归器:一个对异常值具有鲁棒性的模型,CV 得分为 0.4660,表明它对此数据集可能不那么有效。代码中的内容cv_score就像您正在使用的机器学习模型的成绩单。它告诉您模型的表现如何。减少异常值的影响:它还可以减少异常值的影响,因为对数转换显着缩小了数据的范围。因此,cv_score平均分数表明您的模型的预测效果如何。

极光喵的博客 2948

MDT部署实战:除了Office,这些“装机必备”软件也能一键静默安装(含静默参数)

本文详细介绍了如何利用Microsoft Deployment Toolkit(MDT)实现企业级软件的静默安装,包括浏览器、开发工具和系统增强工具等“装机必备”软件的部署方案。通过命令行参数和MSI属性,IT运维团队可以高效构建标准化工作环境,提升部署效率并确保版本一致性。文章还提供了安装顺序控制、结果验证和常见问题排错等高级技巧。

weixin_26985923的博客 172

区域法(zonal method)重构波前

目的:实现区域法的Matlab代码 1.理论介绍 区域法波前重构即从波前探测器测得的波前斜率中恢复出波前的相位值,其分为:休晋模型(Hudgin)[90]、绍契威尔模型(Southwell)[40]和弗雷德模型(Fried)[48]。 1.1 Fried模型,对于N×N微透镜阵列构成的网格: 以3*3的子透镜为例,解释上式,对其展开 改写为矩阵形式: 记作:S=AΦ,A根据N而确定。S是波前探测器测得的斜率,Φ是重构矩阵的相位值。 1.2 而Southwel...

EyRe1的博客 8198

自动识别象棋棋子的OpenCV应用

在计算机视觉领域,OpenCV是一个广泛应用的开源计算机视觉库,它提供了丰富的图像处理和分析工具。本文将介绍如何使用OpenCV实现自动识别象棋棋子的功能,并提供相应的源代码。通过以上代码,我们可以实现对棋盘图像中棋子的自动识别。需要注意的是,以上代码只是一个简单的示例,实际应用中可能需要根据具体情况进行参数调整和算法优化,以获得更好的识别效果。函数利用预处理后的图像,寻找图像中的轮廓,并根据轮廓的面积筛选出可能的棋子轮廓,最后在原图像中提取棋子区域。在主程序中,我们读取输入图像,并调用。

WzisTypescript的博客 908

14、改进的目标检测与图像去模糊算法研究

本文研究了改进的目标检测与图像去模糊算法。改进的YOLOv5s算法在目标检测中通过添加PSA模块和VoVGSCSP结构,在轻量化模型的同时提高了检测的准确性和速度,适用于电力操作安全穿戴设备检测等场景。XT-GAN结合Transformer和生成对抗网络,在图像去模糊任务中有效解决了传统方法的不足,具有更低的计算复杂度和良好的鲁棒性。两种算法为计算机视觉领域的相关任务提供了更高效、准确的解决方案。

c7d8e的博客 215

借助Claude实现Playwright的自动化(MCP Server)

MCP Server自己开发也是可以的,现在也有很多开箱即用的MCP Server,可以在https://github.com/modelcontextprotocol/servers中查找。

Criss@陈磊 4229

vscode中运行gcc -v命令失败了,提示:gcc不是内部或外部命令...如何解决?

🏆本文收录于 《全栈Bug调优(实战版)》 专栏,该专栏专注于分享我在真实项目开发中遇到的各类疑难Bug及其深层成因,并系统提供高效、可复现的解决思路和实操方案。无论你是刚入行的新手开发者,还是拥有多年项目经验的资深工程师,本专栏都将为你提供一条系统化、高质量的问题排查与优化路径,助力你加速成长,攻克技术壁垒,迈向技术价值最大化与职业发展的更高峰🚀!

**My Coding Family** 976

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

上一篇: 自定义过滤器和拦截器实现ThreadLocal线程封闭
下一篇: RocketMQ的push消费方式实现的简直不要太聪明
java_lujj
博客等级 码龄4年 18粉丝 152原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值