目录
一、理解Spring后置处理器
二、Spring后置处理器在IOC容器和bean对象生命周期的切入时机分析
(一)IOC 容器生命周期中的切入时机
(二)Bean 对象生命周期中的切入时机
三、BeanPostProcessor后置器分析
(一)源码分析
(二)具体切入时机分析
(三)InstantiationAwareBeanPostProcessor派生分析
(四)DestructionAwareBeanPostProcessor派生分析
(五)MergeBeanDefinitionPostProcessor
四、BeanFactoryPostProcessor后置器分析
(一)源码展示
(二)切入时机说明
(三)BeanDefinitionRegistryPostProcessor派生分析
五、Spring后置处理器对比分析
源码或官方文章
Spring Framework 中的后置处理器允许在容器实例化 Bean 或者在 Bean 的生命周期中进行操作。从源码上来看的话,其实其扩展机制下的后置处理器其实很多。我们重点放到我们常用的几个上BeanPostProcessor、BeanFactoryPostProcessor来聚焦分析一下。
一、理解Spring后置处理器
提供一种灵活的机制,允许开发人员在 Spring 容器管理的 Bean 生命周期的不同阶段插入自定义的逻辑,从而实现各种需求。注意官方文档中并未直接提及 "Spring 后置处理器" 这个术语,但是从文档中可以看出 Spring 框架提供了一系列的扩展点和接口,这些接口的设计思想和使用方式符合 Spring 后置处理器的特性和用途。我们暂时将这些常用的直接理解为Spring后置处理器。
二、Spring后置处理器在IOC容器和bean对象生命周期的切入时机分析
Spring 后置处理器在 IOC 容器和 Bean 对象生命周期的不同阶段有不同的切入时机:
(一)IOC 容器生命周期中的切入时机
BeanFactoryPostProcessor 的切入时机是在 IOC 容器实例化 BeanDefinition,并将其加载到容器中之后,但在 Bean 实例化之前。它允许对容器中的 BeanDefinition 进行修改,比如修改属性值、添加额外的 BeanDefinition 等。
- BeanDefinitionRegistryPostProcessor 是 BeanFactoryPostProcessor 的子接口,它在 BeanFactoryPostProcessor 之后执行,但在 Bean 实例化之前。它允许进一步修改 BeanDefinitionRegistry 中的 BeanDefinition,比如注册新的 BeanDefinition。
(二)Bean 对象生命周期中的切入时机
BeanPostProcessor 的切入时机是在 Bean 实例化后,但在 Bean 的初始化方法(如果有)被调用之前(postProcessBeforeInitialization()
方法被调用)和之后(postProcessAfterInitialization()
方法被调用)。它允许在 Bean 初始化前后执行自定义处理逻辑,比如初始化之前执行一些预处理,初始化之后执行一些后处理逻辑。
- InstantiationAwareBeanPostProcessor 是 BeanPostProcessor 的子接口,提供了更多的回调方法,如
postProcessBeforeInstantiation()
和postProcessAfterInstantiation()
。它允许在 Bean 实例化之前和之后执行自定义逻辑。 - DestructionAwareBeanPostProcessor 是 BeanPostProcessor 的子接口,它提供了一个额外的回调方法
postProcessBeforeDestruction()
,允许在 Bean 销毁之前执行自定义逻辑。 - MergeBeanDefinitionPostProcessor:实际上是 Spring 内部使用的后置处理器,用于处理合并父子 BeanDefinition 的逻辑。它主要参与了 BeanDefinition 合并的过程,而不是直接影响 Bean 对象的生命周期。因此,在 Bean 对象的生命周期中并没有直接的切入时机与之相关联。
三、BeanPostProcessor后置器分析
(一)源码分析
BeanPostProcessor 接口源码提取如下:
package org.springframework.beans.factory.config;public interface BeanPostProcessor {Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
BeanPostProcessor 接口非常简洁,只定义了两个方法,对于开发人员只需要专注于自定义的逻辑即可,不必关注太多的接口方法。
(二)具体切入时机分析
了解 BeanPostProcessor 接口中的两个方法的具体切入时机:
postProcessBeforeInitialization 方法的切入时机
在 Bean 的初始化方法调用之前被调用。当 Spring 容器完成 Bean 的实例化后,但在 Bean 的初始化方法(如果有)被调用之前,会依次遍历所有注册的 BeanPostProcessor,并调用它们的 postProcessBeforeInitialization()
方法。这个时机可以用于在 Bean 初始化之前执行一些预处理逻辑,比如属性设置、依赖注入、初始化前的校验等。
postProcessAfterInitialization 方法的切入时机
在 Bean 的初始化方法调用之后被调用。当 Spring 容器完成 Bean 的实例化和初始化(包括调用初始化方法)后,会依次遍历所有注册的 BeanPostProcessor,并调用它们的 postProcessAfterInitialization()
方法。这个时机可以用于在 Bean 初始化之后执行一些后处理逻辑,比如初始化后的校验、AOP 代理的创建、与其他 Bean 的关联等。
(三)InstantiationAwareBeanPostProcessor派生分析
InstantiationAwareBeanPostProcessor 接口是 BeanPostProcessor 接口的子接口,用于在 Bean 实例化之前和之后执行自定义逻辑。
package org.springframework.beans.factory.config;public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {// 在 Bean 实例化之前调用,允许修改即将实例化的 Bean 类型default Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException {return null;}// 在 Bean 实例化之前调用,允许返回另一个实例化的 Bean 类型default Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {return bean;}// 在 Bean 实例化之后调用,允许对 Bean 属性进行修改default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {return null;}// 在 Bean 实例化之后调用,允许修改或替换已创建的 Bean 实例default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {return true;}
}
InstantiationAwareBeanPostProcessor 接口定义了四个方法,其中两个继承两个新增:
方法 | 描述 | 返回值 |
---|---|---|
predictBeanType | 在 Bean 实例化之前调用,允许修改即将实例化的 Bean 类型 | 预测的 Bean 类型 |
getEarlyBeanReference | 在 Bean 实例化之前调用,允许返回另一个实例化的 Bean 类型 | 早期引用的 Bean 实例 |
postProcessBeforeInstantiation | 在 Bean 实例化之后调用,允许对 Bean 属性进行修改 | 修改后的 Bean 实例 |
postProcessAfterInstantiation | 在 Bean 实例化之后调用,允许修改或替换已创建的 Bean 实例 | 是否继续调用后续的 BeanPostProcessor |
(四)DestructionAwareBeanPostProcessor派生分析
是 BeanPostProcessor 接口的子接口,提供了一个额外的回调方法用于在 Bean 销毁之前执行自定义逻辑。
package org.springframework.beans.factory.config;public interface DestructionAwareBeanPostProcessor extends BeanPostProcessor {// 在 Bean 销毁之前调用,允许执行一些清理逻辑void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException;
}
切入时机分析:
postProcessBeforeDestruction()
方法在 Bean 销毁之前调用。- 调用时机是在 Spring 容器销毁 Bean 对象之前,允许执行一些清理操作。
- 这个方法的调用发生在 Bean 的生命周期的末尾阶段,即 Bean 即将被销毁之前。
- 我们可以在这个方法中执行一些清理工作,比如释放资源、关闭连接、撤销注册等。
我们可以通过实现这个接口可以确保在 Bean 被销毁时进行一些额外的操作,从而保证系统的稳定性和资源的正确释放等。
(五)MergeBeanDefinitionPostProcessor
MergeBeanDefinitionPostProcessor 并不是 Spring Framework 公开的 API,是 Spring 内部使用的一个工具类,用于处理父子 BeanDefinition 合并的逻辑,通常不会直接暴露给外部使用。
MergeBeanDefinitionPostProcessor 的设计思想是在 BeanDefinition 合并过程中插入自定义的处理逻辑。在 Spring 中,当存在父子 BeanDefinition 时,容器会根据一定的合并规则将它们合并成一个完整的 BeanDefinition。MergeBeanDefinitionPostProcessor 就是为了在这个合并过程中提供扩展点,允许我们对合并后的 BeanDefinition 进行进一步的处理,但本身不能对其进行扩展。
四、BeanFactoryPostProcessor后置器分析
(一)源码展示
BeanFactoryPostProcessor 的切入时机是在 Spring 容器标准初始化之后,但在实例化和配置所有的 BeanDefinition 之后:
package org.springframework.beans.factory.config;import org.springframework.beans.BeansException;public interface BeanFactoryPostProcessor {// 在标准初始化之后修改应用程序上下文的工厂void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
内部定义了一个方法 postProcessBeanFactory()
,这个方法在标准初始化之后调用,用于修改应用程序上下文的工厂。在这个方法中,我们可以对 BeanFactory 进行各种自定义处理,比如注册额外的 BeanDefinition、修改已存在的 BeanDefinition、添加属性编辑器等。
分析源码实现:postProcessBeanFactory()
方法接收一个 ConfigurableListableBeanFactory 参数,通过这个参数可以获取到应用程序上下文的 BeanFactory,从而对其进行相应的操作。通常,我们会在这个方法中通过调用 BeanFactory 的各种方法来实现自己的逻辑。
(二)切入时机说明
从一开始的原始图中来看的话:BeanFactoryPostProcessor 的切入时机是在 Spring 容器标准初始化之后,但在实例化和配置所有的 BeanDefinition 之后,我们可以具体展开在回顾一下:
- Spring 容器启动:当应用程序启动时,Spring 容器会加载并初始化所有的 BeanDefinition。
- BeanFactory 初始化完成:在 BeanFactory 初始化完成之后,容器会调用所有已注册的 BeanFactoryPostProcessor 的 postProcessBeanFactory() 方法。
- 修改 BeanFactory:在 postProcessBeanFactory() 方法中可以对 BeanFactory 进行各种自定义的操作。这包括但不限于:注册额外的 BeanDefinition、修改已存在的 BeanDefinition、添加属性编辑器、设置属性值等。
- Bean 实例化前:其在 Bean 实例化之前被调用的,因此它主要用于对 BeanDefinition 进行修改,而不是对已实例化的 Bean 进行操作。
(三)BeanDefinitionRegistryPostProcessor派生分析
是 BeanFactoryPostProcessor 的子接口。与 BeanFactoryPostProcessor 不同的是,BeanDefinitionRegistryPostProcessor 能够访问到 BeanDefinitionRegistry(Bean 定义注册表),可以动态地注册、修改和删除 BeanDefinition。
package org.springframework.beans.factory.support;import org.springframework.beans.factory.config.BeanFactoryPostProcessor;public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {// 在标准初始化之后修改应用程序上下文的内部 bean 工厂的注册表void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry);
}
继承自 BeanFactoryPostProcessor 接口,在 postProcessBeanFactory 方法外还新增了一个方法 postProcessBeanDefinitionRegistry,这个方法在标准初始化之后修改应用程序上下文的内部 bean 工厂的注册表。
在这个接口中,postProcessBeanDefinitionRegistry 方法接收一个 BeanDefinitionRegistry 参数,通过这个参数可以访问到应用程序上下文的 BeanDefinitionRegistry,即 Bean 定义注册表。我们可以在这个方法中对注册表进行各种自定义处理,比如注册额外的 BeanDefinition、修改已存在的 BeanDefinition、删除不需要的 BeanDefinition 等。
五、Spring后置处理器对比分析
特性 | BeanPostProcessor | BeanFactoryPostProcessor |
---|---|---|
作用范围 | 单个 Bean 实例 | 整个容器的 BeanDefinition 集合 |
接口层次 | BeanPostProcessor 接口 | BeanFactoryPostProcessor 接口 |
方法调用时机 | Bean 实例化后,初始化前后 | 容器启动过程中,标准初始化之后 |
处理对象 | 单个 Bean 实例 | 整个容器的 BeanDefinition 集合 |
主要功能 | 对 Bean 进行增强,如 AOP、日志等 | 对容器进行定制化处理,如注册 BeanDefinition、修改属性等 |
使用场景 | 需要对单个 Bean 进行增强的场景 | 需要对整个容器进行定制化处理的场景 |
源码或官方文章
Java-based Container Configuration :: Spring Framework
Bean Scopes :: Spring Framework
Container Overview :: Spring Framework