在实际应用中,通常
不会同时使用@PostConstruct和InitializingBean#afterPropertiesSet(),
也不会同时使用@PreDestroy和DisposableBean#destroy(),
因为它们是重复的机制。
此外,还需要注意的是,Aware接口的方法调用通常发生在依赖注入之后,但在@PostConstruct之前。这是因为Aware接口提供的方法允许Bean访问其在Spring容器中的环境和配置信息,这可能需要依赖项已经被注入。
调用顺序 | 方法/注解 | 描述 |
---|---|---|
1 | 构造方法 | 通过调用Bean的构造方法来创建Bean对象 |
2 | @Autowired | 用于自动装配Bean的依赖项,通常在构造方法之后立即发生 |
3 | Aware接口方法 | 如果Bean实现了Aware接口,会调用相应的方法,使Bean能够访问Spring容器的特定资源 |
4 | @PostConstruct | 在Bean的依赖项注入完成后被调用,用于执行Bean的初始化逻辑 |
5 | InitializingBean#afterPropertiesSet() | 如果Bean实现了InitializingBean接口,在所有的属性设置完毕并且依赖注入完成后调用 |
6 | @Bean#initMethod() | 如果在Bean的配置中指定了init-method属性,会调用指定的初始化方法 |
调用顺序 | 方法/注解 | 描述 |
---|---|---|
1 | @PreDestroy | 在Bean即将被销毁之前调用,允许Bean执行一些资源清理的逻辑 |
2 | DisposableBean#destroy() | 如果Bean实现了DisposableBean接口,在Bean销毁时调用 |
3 | @Bean#destroyMethod() | 如果在Bean的配置中指定了destroy-method属性,会调用指定的销毁方法 |
生命周期阶段 | 事件/回调方法 | 相关的BeanPostProcessor 方法 |
备注 |
---|---|---|---|
实例化前 | 无直接事件 | BeanFactoryPostProcessor.postProcessBeanFactory |
对BeanFactory进行后处理,此时Bean尚未实例化。 |
实例化 | Bean构造函数被调用 | 无直接BeanPostProcessor 方法 |
Bean对象被创建,但属性尚未注入。 |
属性注入后 | 无直接事件 | BeanPostProcessor.postProcessBeforeInitialization |
在Bean初始化之前调用,此时Bean的属性已注入,但自定义初始化方法尚未调用。 |
初始化 | InitializingBean.afterPropertiesSet 或 自定义的init 方法 |
无直接BeanPostProcessor 方法,但在上一阶段和下一阶段之间执行 |
执行Bean的自定义初始化逻辑。 |
初始化后 | 无直接事件 | BeanPostProcessor.postProcessAfterInitialization |
在Bean初始化方法执行完毕后调用,此时Bean已完全初始化。 |
销毁前 | 无直接事件 | 无直接BeanPostProcessor 方法 |
在Bean销毁之前,可以通过DisposableBean.destroy 或自定义的destroy-method 进行资源清理。 |
销毁 | DisposableBean.destroy 或 自定义的destroy 方法 |
无直接BeanPostProcessor 方法 |
执行Bean的自定义销毁逻辑。 |
请注意,BeanFactoryPostProcessor
与BeanPostProcessor
不同,它处理的是BeanFactory
,而不是单个Bean。此外,BeanPostProcessor
的两个方法postProcessBeforeInitialization
和postProcessAfterInitialization
分别在Bean的初始化方法之前和之后被调用。
此表格主要是为了展示Bean的生命周期阶段和与之相关的回调方法或事件。在实际应用中,开发者可以通过实现相应的接口或配置自定义的初始化/销毁方法来参与Bean的生命周期管理。
BeanPostProcessor
子类及其调用顺序相关因素子类/实现 | 调用顺序确定因素 | 描述 |
---|---|---|
自定义BeanPostProcessor | 注册顺序 | 按照在Spring配置中定义或扫描的顺序进行调用。 |
实现了Ordered接口的BeanPostProcessor | 实现优先级 | 通过实现Ordered 接口的getOrder() 方法提供一个顺序值,值越小优先级越高。 |
使用@Order注解的BeanPostProcessor | 注解优先级 | 使用@Order 注解并指定一个值来确定调用顺序,值越小优先级越高。 |
依赖关系的BeanPostProcessor | 依赖关系 | 如果存在依赖关系,被依赖的BeanPostProcessor会先被调用。 |
其他默认BeanPostProcessor | 默认顺序 | 没有指定顺序的BeanPostProcessor按照默认顺序调用,通常基于注册顺序。 |
请注意,这个表格是为了说明影响BeanPostProcessor
子类调用顺序的不同因素。实际上,在编写自定义的BeanPostProcessor
时,并不一定会直接扩展BeanPostProcessor
接口的子类,而是直接实现BeanPostProcessor
接口,并根据需要实现Ordered
接口或使用@Order
注解来指定调用顺序。
此外,表格中的“自定义BeanPostProcessor”指的是开发者自己实现的BeanPostProcessor
接口,而不是指一个具体的子类。开发者在实现自定义的BeanPostProcessor
时,应该遵循Spring框架的规范,确保处理器能够在Bean的生命周期中正确地执行。
ApplicationContext是我们常用的IOC容器,而他的顶层接口便是BeanFactory,ApplicationContext对BeanFactory做了拓展,功能更加强大。
@Component
public class SpringtUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext = null;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SpringtUtil.applicationContext = applicationContext;
}
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
}
用于在spring容器刷新之前初始化Spring ConfigurableApplicationContext的回调接口。
通常用于需要对应用程序上下文进行编程初始化的web应用程序中。例如,根据上下文环境注册属性源或激活配置文件等。
public class MyApplicationContextInitializer implements ApplicationContextInitializer {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
System.out.println("-----MyApplicationContextInitializer initialize-----");
}
}
@SpringBootApplication
public class MySpringBootApplication {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(MySpringBootApplication.class);
application.addInitializers(new MyApplicationContextInitializer());
application.run(args);
}
}
context.initializer.classes=org.springframework.boot.demo.common.MyApplicationContextInitializer
org.springframework.context.ApplicationContextInitializer=org.springframework.boot.demo.common.MyApplicationContextInitializer
BeanPostProcessor,中文名 Bean的后置处理器,在Bean创建的过程中起作用。
BeanPostProcessor是Bean在创建过程中一个非常重要的扩展点,因为每个Bean在创建的各个阶段,都会回调BeanPostProcessor及其子接口的方法。
@Component
public class LoggingBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.err.println("Before Initialization : " + bean.getClass().getName());
return bean; // 直接返回传入的bean,不做额外处理
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
父类名 | 类名 | 作用 | 实际使用 |
---|---|---|---|
BeanPostProcessor |
AutowiredAnnotationBeanPostProcessor |
处理 @Autowired 和 @Value 注解,实现自动装配 |
在 Spring 应用程序中自动注入依赖 |
BeanPostProcessor |
RequiredAnnotationBeanPostProcessor |
检查带有 @Required 注解的 bean 属性是否已设置 |
确保必需属性被正确注入 |
BeanPostProcessor |
CommonAnnotationBeanPostProcessor |
处理 JSR-250 注解(如 @PostConstruct , @PreDestroy , @Resource ) |
在 bean 生命周期中调用注解方法,处理资源注入 |
BeanPostProcessor |
PersistenceAnnotationBeanPostProcessor |
扫描并处理 JPA 相关注解(如 @Entity ) |
集成 JPA 实体类到 Spring 应用程序中 |
BeanPostProcessor |
AsyncAnnotationBeanPostProcessor |
处理 @Async 注解,使方法异步执行 |
在 Spring 应用程序中创建异步任务 |
BeanPostProcessor |
ScheduledAnnotationBeanPostProcessor |
处理 @Scheduled 注解,按计划执行方法 |
在 Spring 应用程序中创建定时任务 |
BeanPostProcessor |
自定义 BeanPostProcessor |
允许开发者自定义 bean 的初始化逻辑 | 插入自定义代码到 bean 初始化过程 |
请注意,这个表格是为了提供信息而简化的,并且可能不包含所有 BeanPostProcessor
的实现。此外,随着 Spring 框架的发展,可能会有新的实现类被添加或现有类的用途发生变化。因此,建议参考 Spring 官方文档以获取最新和详细的信息。
InitializingBean接口为bean提供了属性初始化后的处理方法,它只有一个afterPropertiesSet方法,凡是继承该接口的类,在bean的属性初始化后都会执行该方法。
@Component
public class MyInitializingBean implements InitializingBean {
public MyInitializingBean() {
System.out.println("我是MyInitializingBean构造方法执行...");
}
@PostConstruct
public void postConstruct() {
System.out.println("我是postConstruct方法执行...");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("我是afterPropertiesSet方法执行...");
}
@Bean(initMethod = "init")
public MyInitializingBean test() {
return new MyInitializingBean();
}
public void init(){
System.out.println("我是init方法执行...");
}
// 打印顺序:
// 构造方法 > postConstruct >afterPropertiesSet > init方法
}