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的定义和注册过程。
特性 | ImportSelector | ImportBeanDefinitionRegistrar |
---|---|---|
控制级别 | 较高级别 | 底层级别 |
返回值 | 返回类名字符串数组 | 无返回值,直接操作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的所有属性填充(依赖注入)
主要作用:
属性填充控制:决定是否对Bean进行依赖注入
实例化后处理:在依赖注入前对Bean进行预处理
条件性初始化:根据条件决定Bean的初始化策略
性能优化:避免不必要的依赖注入操作
安全控制:基于权限控制Bean的初始化过程
InstantiationAwareBeanPostProcesser#postProcessProperties
下一个切入点则是InstantiationAwareBeanPostProcesser的postProcessProperties方法,该方法的作用会将bean对象对应的PropertyValues中封装赋值和注入的属性和依赖对象时机应用到bean对象的实例中去,它会收集bean对象所属的class的标注了注解的属性以及方法,来对其进行反射赋值/调用。在此过程中相当于扩展类后置处理器的属性赋值+依赖注入的逻辑
postProcessProperties
的主要作用是:
属性值转换:修改、转换或验证属性值
自定义注入:实现比Spring默认机制更复杂的依赖解析
动态属性:解析占位符、加密值或从外部源获取属性
环境适配:根据环境调整属性值
AOP集成:确保注入适当的代理对象
BeanPostProcessor
在执行完属性赋值和依赖注入的操作之后,下一个核心步骤是initializeBean方法,这个方法主要是进行BeanPostProcessor的postProcessBeforeInitialization和postProcessAfterInitialization方法。
postProcessBeforeInitialization在Bean的初始化方法(如@PostConstruct
、InitializingBean.afterPropertiesSet()
、自定义init-method)之前执行,用于对Bean进行预处理。postProcessAfterInitialization在Bean的初始化方法(如@PostConstruct
、InitializingBean.afterPropertiesSet()
、自定义init-method)之后执行,用于对Bean进行后处理,最常见的是创建AOP代理。
特性 | postProcessBeforeInitialization | postProcessAfterInitialization |
---|---|---|
执行时机 | 初始化方法之前 | 初始化方法之后 |
主要用途 | 准备、验证、预处理 | 包装、代理创建、注册 |
修改Bean | 通常不替换Bean实例 | 经常返回包装后的Bean实例 |
AOP相关 | 准备代理创建 | 实际创建代理 |
异常影响 | 异常会阻止初始化方法执行 | 异常会使Bean创建失败 |
postProcessBeforeInitialization:
时机:初始化方法之前
用途:预处理、验证、准备
典型场景:设置通用属性、验证状态、准备代理创建
postProcessAfterInitialization:
时机:初始化方法之后
用途:后处理、包装、代理创建
典型场景:AOP代理创建、监控注册、事件发布