← 全部文章

Spring中跟生命周期相关的注解和接口

@PostConstruct、@PreDestroy等等

本文目录 12 节
Spring中跟生命周期相关的注解和接口封面

注解

@PostConstruct

它的执行时机是这样的:

创建对象(new)
注入依赖(@Autowired / @Resource)
执行 @PostConstruct 方法
Bean 初始化完成,可以被使用

也就是用来做初始化逻辑。例如,初始化缓存、加载配置、预热数据、启动定时任务、检查依赖是否正常。

在@PostConstruct中,可以使用已经注入的依赖。虽然 Bean 的初始化过程尚未结束,但对象实例已经创建且属性已注入。

注意:该注解在 Spring Boot 2.x 中位于 javax.annotation 包,Spring Boot 3.x 迁移至 Jakarta EE 后改为 jakarta.annotation 包,升级时需留意。

@PreDestroy

它是@PostConstruct的反向操作。

被这个注解修饰的方法,会在Spring容器销毁它前执行。

同样受 Jakarta EE 迁移影响,Spring Boot 3.x 中需使用 jakarta.annotation.PreDestroy。


接口

CommandLineRunner

实现了这个接口的Bean,Spring Boot启动完成之后会执行这个Bean的run方法。因此,你需要将实现了这个接口的类注册为Bean,否则Spring扫描不到它。

@Component
public class TestRunner implements CommandLineRunner {
    @Override
    public void run(String... args) {
        System.out.println("Spring Boot 启动完成");
    }
}

ApplicationRunner

它和CommandLineRunner是一样的,只不过参数更强——接收的是ApplicationArguments对象,可以方便地解析命名参数(如 --key=value)。

@Component
public class TestRunner implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) {
        System.out.println("Spring Boot 启动完成");
    }
}

附:Bean的生命周期

实例化阶段

Spring容器根据Bean定义(BeanDefinition),通过反射调用构造方法或工厂方法创建一个Bean的实例。但此时的 Bean 还只是一个空壳,字段均为默认值,尚未注入任何依赖。

属性赋值阶段

Spring扫描Bean中的注解(如 @Autowired、@Resource、@Value),将依赖的其他 Bean 或配置值注入到当前 Bean 中。

如果存在循环依赖,Spring 的”三级缓存”机制主要在这个阶段发挥作用。

初始化阶段

Aware 接口回调

如果 Bean 实现了 Aware 系列接口,Spring会把容器内部的资源注入进去。

  • BeanNameAware:获取 Bean 的 ID。
  • BeanFactoryAware:获取当前的 Bean 工厂。
  • ApplicationContextAware:获取完整的 Spring 容器上下文。

BeanPostProcessor 前置处理

执行所有注册的 BeanPostProcessor 的 postProcessBeforeInitialization 方法。

执行初始化逻辑

  • 执行 @PostConstruct 注解的方法。
  • 执行 InitializingBean 接口的 afterPropertiesSet 方法。
  • 执行 XML 或 @Bean 中定义的 init-method。

BeanPostProcessor 后置处理

执行 postProcessAfterInitialization 方法。

这里有一个细节要注意:AOP(面向切面编程)的代理对象通常就是在这一步生成的。如果一个 Bean 需要被增强(比如加事务、日志),这一步返回的就不再是原始对象,而是代理对象。

使用阶段

这个阶段Bean初始化完成,被放入IOC容器中,可以随时被调用。

销毁阶段

当容器关闭(如 Web 应用停止)时,会触发销毁流程。

  • 执行 @PreDestroy 注解的方法。
  • 执行 DisposableBean 接口的 destroy 方法。
  • 执行 @Bean(destroyMethod = "...") 或 XML 中定义的 destroy-method。

评论