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

Spring原理揭秘--ApplicationContext初始化中的扩展点

在整个refresh方法中有许许多多的扩展点可供开发者利用切入,下面我们来就来盘点一下在整个refresh方法中的扩展点都有哪些

BeanFactory准备阶段

在BeanFactory准备阶段中第一个出现可切入的步骤是在invokeBeanFactoryPostProcessors中

ImportSelector和ImportBeanDefinitionRegister

在这个阶段中往往是首先执行ConfigurationClassPostProcesser类,在执行的过程中则会调用

ConfigurationClassPostProcessor是一个BeanFactoryPostProcessor,专门负责处理@Configuration注解的配置类,解析其中的Bean定义并注册到Spring容器中

ImportSelector和ImportBeanDefinitionRegister的回调方法来进行扩展操作,因此开发者可以自定义实现ImportSelector和ImportBeanDefinitionRegister的实现类这样就能自定义扩展逻辑,对于ImportSelector和ImportBeanDefinitionRegister的区别在于:ImportSelector用于动态选择要导入的配置类,返回的是类的全限定名数组,由Spring来实例化和处理这些配置类。而ImportBeanDefinitionRegister则用于以编程方式直接注册Bean定义,提供了更底层的控制,可以自定义Bean的定义和注册过程。

特性ImportSelectorImportBeanDefinitionRegistrar
控制级别较高级别底层级别
返回值返回类名字符串数组无返回值,直接操作Registry
灵活性相对较低非常高
使用场景简单的条件导入复杂的Bean注册逻辑
Bean定义控制有限控制完全控制Bean定义
性能较好更灵活但可能稍复杂

BeanDefinitionRegistryPostProcessor

在执行完前面的扩展逻辑之后则会执行BeanDefinitionRegistryPostProcessor接口的实现类,使用BeanDefinitionRegistryPostProcessor可以获取到BeanDefinitionRegistry对象,利用其可以直接向ioc容器中进行编程式注入新的BeanDefinition以及移除容器中已有的beanDefinition,自定义的BeanDefinitionRegistryPostProcessor执行时机往往是比内置的ConfigurationClassPostProcessor更加靠后执行,但是也可以将自定义的BeanDefinitionRegistryPostProcessor实现PriorityOrdered接口,声明较高的执行优先级即可在ConfigurationClassPostProcessor之前进行执行

BeanFactoryPostProcesser

BeanFactoryPostProcesser的切入时机紧跟着BeanDefinitionRegistryPostProcessor之后而执行,而BeanDefinitionRegistryPostProcessor与BeanFactoryPostProcesser的区别在于获取的参数不同,BeanDefinitionRegistryPostProcessor是直接获取BeanDefinitionRegistry,而BeanFactoryPostProcesser则是获取的BeanFactory,我们知道对于beanDefinition的注入往往是直接通过BeanDefinitionRegistry来进行管理的,因此BeanFactoryPostProcesser原则上无法直接向ioc容器进行beanDefinition注入新的beanDefinition而是在原有的beanDefinition基础上进行修改(如果想BeanFactoryPostProcessor 也可以通过转换为 BeanDefinitionRegistry 来注册新的BeanDefinition)

Bean实例化和完成阶段

第一个环节是ApplicationContext的准备阶段,那么接下来就是最核心的getBean阶段也就是Bean的实例化和初始化的阶段

InstantiationAwareBeanPostProcesser#postProcessBeforeInstantiation

在对象实例化之前InstantiationAwareBeanPostProcesser可以前置拦截bean对象的实例化操作调用postProcessBeforeInstantiation的方法,这个方法允许完全绕过Spring的默认实例化机制,返回一个自定义的Bean实例。参数获取的是当前bean对象的class类型以及bean对象的名称,如果当前方法返回的是null则代表不参与拦截对象的创建动作。

如果任何 InstantiationAwareBeanPostProcessor 的 postProcessBeforeInstantiation 方法返回非null对象,那么:

  • ✅ 这个对象会直接作为Bean实例

  • ❌ 跳过默认的构造函数实例化

  • ❌ 跳过 postProcessAfterInstantiation

  • ❌ 跳过 属性填充(依赖注入)

  • ❌ 跳过 BeanPostProcessor的初始化回调

  • ✅ 但会执行 postProcessAfterInitialization

SmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors

如果实例化前没有被拦截,那么就会通过构造方法来创建对象。如果一个bean对象的所属类型中定义了多个构造方法,那么选择何时的构造方法去创建对象就是一个很重要的一步。筛选构造方法的核心动作会在SmartInstantiationAwareBeanPostProcessor中调用determineCandidateConstructors方法来获取可选择的构造方法,用于在Bean实例化阶段确定使用哪个构造函数来创建Bean实例。

返回值的含义

  • 非null数组:Spring将只考虑这些构造函数

  • 空数组:表示没有合格的构造函数,可能导致创建失败

  • null:让Spring使用默认的构造函数解析逻辑

MergedBeanDefinitionPostProcessir#postProcessMergedBeanDefinition

MergedBeanDefinitionPostProcessor是Spring框架中一个重要的扩展点,它在Bean定义合并完成后、Bean实例化之前执行,主要用于处理和缓存Bean的元数据信息。会回调所有子类的postProcessMergedBeanDefinition方法来进行bean对象的注解信息的解析收集,为后续的属性赋值等动作进行数据的缓存

InstantiationAwareBeanPostProcesser#postProcessAfterInstantiation

InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation 是Spring Bean生命周期中一个重要的扩展点,它在Bean实例化之后、属性填充(依赖注入)之前执行。

这个方法返回一个布尔值,用于决定是否对当前Bean进行属性填充:

  • 返回 true:继续后续的属性填充过程(默认行为)

  • 返回 false跳过当前Bean的所有属性填充(依赖注入)

主要作用:

  1. 属性填充控制:决定是否对Bean进行依赖注入

  2. 实例化后处理:在依赖注入前对Bean进行预处理

  3. 条件性初始化:根据条件决定Bean的初始化策略

  4. 性能优化:避免不必要的依赖注入操作

  5. 安全控制:基于权限控制Bean的初始化过程

InstantiationAwareBeanPostProcesser#postProcessProperties

下一个切入点则是InstantiationAwareBeanPostProcesser的postProcessProperties方法,该方法的作用会将bean对象对应的PropertyValues中封装赋值和注入的属性和依赖对象时机应用到bean对象的实例中去,它会收集bean对象所属的class的标注了注解的属性以及方法,来对其进行反射赋值/调用。在此过程中相当于扩展类后置处理器的属性赋值+依赖注入的逻辑

postProcessProperties 的主要作用是:

  1. 属性值转换:修改、转换或验证属性值

  2. 自定义注入:实现比Spring默认机制更复杂的依赖解析

  3. 动态属性:解析占位符、加密值或从外部源获取属性

  4. 环境适配:根据环境调整属性值

  5. AOP集成:确保注入适当的代理对象

BeanPostProcessor

在执行完属性赋值和依赖注入的操作之后,下一个核心步骤是initializeBean方法,这个方法主要是进行BeanPostProcessor的postProcessBeforeInitialization和postProcessAfterInitialization方法。

postProcessBeforeInitialization在Bean的初始化方法(如@PostConstructInitializingBean.afterPropertiesSet()、自定义init-method)之前执行,用于对Bean进行预处理。postProcessAfterInitialization在Bean的初始化方法(如@PostConstructInitializingBean.afterPropertiesSet()、自定义init-method)之后执行,用于对Bean进行后处理,最常见的是创建AOP代理

特性postProcessBeforeInitializationpostProcessAfterInitialization
执行时机初始化方法之前初始化方法之后
主要用途准备、验证、预处理包装、代理创建、注册
修改Bean通常不替换Bean实例经常返回包装后的Bean实例
AOP相关准备代理创建实际创建代理
异常影响异常会阻止初始化方法执行异常会使Bean创建失败

postProcessBeforeInitialization:

  • 时机:初始化方法之前

  • 用途:预处理、验证、准备

  • 典型场景:设置通用属性、验证状态、准备代理创建

postProcessAfterInitialization:

  • 时机:初始化方法之后

  • 用途:后处理、包装、代理创建

  • 典型场景AOP代理创建、监控注册、事件发布

http://www.dtcms.com/a/458076.html

相关文章:

  • wordpress 多站点主题php做视频网站有哪些
  • 南京手机网站制作中山古镇做网站的公司
  • 深圳市建设局质监站官方网站大数据营销方式有哪些
  • 深度学习-Kaggle实战1(房价预测)
  • 邢台高端网站建设公司wordpress 单页模板
  • 有设计师做的装修效果图的网站关于做营销型网站的建议
  • C#+WPF+Opencv模块化开发视觉对位系统
  • 网站专业优化公司广州工商学院门户网站
  • 贪心:Stall Reservations S
  • 商务网站怎么做wordpress模板 更换
  • 企业建设网站的目的wordpress路由与模板调用
  • 滕州住房和城乡建设局网站企业网站设计建设
  • C4D域功能深度解析:随机域、着色器域、声音域、公式域与Python域详解
  • SQL 面试题解析:如何用多表查询写用户订单统计?
  • 建设网站需要收费吗wordpress前台注册登录弹窗代码
  • 双通道记忆网络架构在实际部署时平衡计算资源
  • 网站与域名的区别提供中山精品网站建设
  • 从定性到量化:为何指标是非功能性需求的灵魂与尺度
  • UV环境+UV环境中CUDA安装
  • 一家专门做动漫的网站钓鱼网站源码
  • 网站打开慢 可以只换空间不换域名吗在国外建设网站
  • Oracle 11gR2 RMAN备份
  • C++---》stl : pair 从使用到模拟实现
  • 自己做的网站很卡百度seo规则最新
  • 网站建设管理教程视频厦门网站建设哪家比较好
  • Java-Spring入门指南(二十一)Thymeleaf 视图解析器
  • wordpress phpdisk上海做网站seo
  • 徐州网站简介校园网站建设需要什么
  • mysql基础【SQL语句】
  • 二手车网站程序霍山网站建设