概述
拓展接口 | 作用 |
---|---|
BeanFactoryPostProcessor | 此接口提供了一个机会,在bean实例化之前修改bean的定义,PropertyPlaceholderConfigurer,就是在这个扩展点上对 Bean 属性中的占位符进行替换。 |
BeanDefinitionRegistryPostProcessor | 它扩展自BeanFactoryPostProcessor,在执行 BeanFactoryPostProcessor 的功能前,提供了可以添加 Bean Definition 的能力,允许在初始化一般 Bean 前,注册额外的 Bean,spring注解实现类ConfigurationClassPostProcessor就是继承了这个接口 |
BeanPostProcessor | 提供了在 Bean 初始化之前和之后插入自定义逻辑的能力。与 BeanFactoryPostProcessor 的区别是处理的对象不同,BeanFactoryPostProcessor 是对 BeanFactory 进行处理,BeanPostProcessor 是对 Bean 进行处理,Spring AOP就是依赖该接口实现的 |
InitializingBean | 可以在 Bean 初始化完成,所有属性设置完成后执行特定逻辑,例如对自动装配对属性进行验证等。 |
DisposableBean | 用于在 Bean 被销毁前执行特定的逻辑,例如做一些回收工作等。ApplicationListener,用来监听 Spring 的标准应用事件或者自定义事件。 |
PS:BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor、BeanPostProcessor可以通过实现 Ordered 和PriorityOrdered 接口来指定执行顺序。实现 PriorityOrdered 接口的 processor 会先于实现 Ordered 接口的执行。
BeanFactoryPostProcessor
主要功能
- 修改Bean定义
- 在Spring加载所有bean定义后,但在它开始实例化这些bean之前,
BeanFactoryPostProcessor
会被调用。这意味着我们可以使用它来修改这些bean定义。
- 在Spring加载所有bean定义后,但在它开始实例化这些bean之前,
- 更改属性值
- 我们可以更改bean的属性或依赖,这在某些场景下,如需要根据环境或其他外部因素动态地配置bean时,会非常有用。
- 添加或删除Bean定义
- 不仅可以修改现有的bean定义,还可以添加新的bean定义或删除现有的bean定义。
- 应用多个BeanFactoryPostProcessors
- 如果有多个
BeanFactoryPostProcessor
,我们可以通过实现Ordered
接口来控制它们的执行顺序。
- 如果有多个
Demo
java
public class BeanFactoryPostProcessorApplication {
public static class TestBean {
public void show() {
System.out.println("instance: " + this);
}
}
public static class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("修改bean的定义");
BeanDefinition beanDefinition = beanFactory.getBeanDefinition("beanFactoryPostProcessorApplication.TestBean");
beanDefinition.setScope(BeanDefinition.SCOPE_PROTOTYPE);
System.out.println("将mySimpleBean从默认的单例修改成多例");
System.out.println("修改bean的定义已完成");
}
}
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
TestBean.class,
MyBeanFactoryPostProcessor.class
);
TestBean mySimpleBean1 = context.getBean(TestBean.class);
TestBean mySimpleBean2 = context.getBean(TestBean.class);
mySimpleBean1.show();
mySimpleBean2.show();
}
}
BeanDefinitionRegistryPostProcessor
主要功能
- 注册新的 Bean 定义
- 该接口提供了一个机制,允许在 Spring 容器完成其标准初始化(即加载所有 bean 定义)之后,但在任何 bean 实例化之前,动态注册新的 bean 定义。
- 修改现有的 Bean 定义
- 除了能够添加新的 bean 定义,
BeanDefinitionRegistryPostProcessor
还可以修改已经注册的 bean 定义。例如,它可以修改 bean 的属性值、构造函数参数或其它设置。
- 除了能够添加新的 bean 定义,
- 控制
BeanFactoryPostProcessor
的执行顺序- 因为
BeanDefinitionRegistryPostProcessor
是BeanFactoryPostProcessor
的子接口,它的实现还可以控制BeanFactoryPostProcessor
的执行顺序。这是因为在 Spring 容器启动时,所有的BeanDefinitionRegistryPostProcessor
beans 首先会被实例化和调用,然后才是其他的BeanFactoryPostProcessor
beans。
- 因为
- 基于条件的 Bean 注册
- 可以利用
BeanDefinitionRegistryPostProcessor
来基于特定的运行时条件(例如类路径上是否存在某个特定的类)来决定是否注册某个 bean。
- 可以利用
- 扩展点以实现高级配置
- 对于复杂的应用或框架,这个接口提供了一个扩展点,可以在初始化过程中进行更高级的配置,如加载外部的配置或执行特殊的验证逻辑。
Demo
java
public class BeanFactoryPostProcessorApplication {
public static class TestBean {
public void show() {
System.out.println("instance: " + this);
}
}
public static class MyBeanFactoryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("修改bean的定义");
BeanDefinition beanDefinition = beanFactory.getBeanDefinition("beanFactoryPostProcessorApplication.TestBean");
beanDefinition.setScope(BeanDefinition.SCOPE_PROTOTYPE);
System.out.println("将mySimpleBean从默认的单例修改成多例");
System.out.println("修改bean的定义已完成");
}
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
System.out.println("开始新增Bean定义");
// 创建一个新的 BeanDefinition 对象
BeanDefinition beanDefinition = new RootBeanDefinition(TestBean.class);
// 使用 registry 来注册这个新的 bean 定义
registry.registerBeanDefinition("beanFactoryPostProcessorApplication.TestBean", beanDefinition);
System.out.println("完成新增Bean定义");
}
}
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
MyBeanFactoryPostProcessor.class
);
TestBean mySimpleBean1 = context.getBean(TestBean.class);
TestBean mySimpleBean2 = context.getBean(TestBean.class);
mySimpleBean1.show();
mySimpleBean2.show();
}
}
BeanPostProcessor与InitializingBean
BeanPostProcessor主要功能
修改 Bean 属性:在 Bean 初始化之前或之后,可以修改 Bean 的属性。例如,可以根据某些条件为 Bean 的某些属性设置默认值。
验证 Bean 的状态:在 Bean 初始化完成后,可以检查 Bean 的状态,确保它满足某些条件或约束。
返回代理 Bean:最常见的用例是返回一个代理(proxy)来包装原始的 Bean。例如,Spring AOP 使用它来为目标 Bean 创建代理,从而实现切面的功能。
改变返回的 Bean 类型:可以完全替换一个 Bean 的实例,返回一个不同类型的对象。这是一个高级用例,但在某些场景中可能是必要的
InitializingBean主要功能
-
初始化回调
InitializingBean
接口为 Spring 容器提供了一个机制,以确保在 bean 的所有属性都被设置后,但在 bean 被其他组件使用之前,可以执行某些初始化逻辑或操作。
-
属性验证
- 在
afterPropertiesSet
方法中,我们可以验证 bean 的属性是否都已正确设置,特别是一些必要的属性。
- 在
-
自定义初始化逻辑
- 如果 bean 需要进行特定的初始化操作,如开启资源、连接数据库、启动某些线程或其他任何初始化活动,那么这些操作可以在
afterPropertiesSet
方法中进行。
- 如果 bean 需要进行特定的初始化操作,如开启资源、连接数据库、启动某些线程或其他任何初始化活动,那么这些操作可以在
-
生命周期管理
InitializingBean
是 Spring 生命周期中的一个关键点,它在属性注入 (Property Injection
) 之后和使用 bean 之前被调用。这提供了一个干净的生命周期钩子,可以用来确保 bean 在被使用之前是完全准备好的。
PS:尽管 InitializingBean
提供了一个初始化 bean 的方式,但现代的 Spring 我们更倾向于使用 @PostConstruct
注解,因为它是 JSR-250 的一部分,不依赖于 Spring 特定的接口。
Demo
java
public class BeanFactoryPostProcessorApplication {
public static class TestBean implements InitializingBean {
public TestBean() {
System.out.println("1. TestBean 构造函数");
}
public void show() {
System.out.println("instance: " + this);
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("3. afterPropertiesSet");
}
}
public static class MyBeanFactoryPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("2. postProcessBeforeInitialization");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("4. postProcessAfterInitialization");
return bean;
}
}
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
MyBeanFactoryPostProcessor.class,
TestBean.class
);
TestBean mySimpleBean1 = context.getBean(TestBean.class);
mySimpleBean1.show();
}
}
DisposableBean
主要功能
- 销毁回调
- 当 bean 被 Spring 容器销毁时,如果它实现了
DisposableBean
接口,容器会自动调用其destroy()
方法。这为 beans 提供了一个机会在销毁之前执行任何必要的清理操作。
- 当 bean 被 Spring 容器销毁时,如果它实现了
Demo
java
public class BeanFactoryPostProcessorApplication {
public static class TestBean implements DisposableBean {
@Override
public void destroy() {
System.out.println("destroy");
}
}
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
TestBean.class
);
context.close();
}
}