在项目开发中,有时候会在 Spring 应用启动后做一些初始化的操作,比如数据字典缓存,状态通知,配置读取等操作。
SpringBoot 提供了多种方式可以让开发者在容器启动后来执行一个任务:
- 使用
@PostConstruct
注解 - 通过
ApplicationListener
监听SpringBoot 启动过程中的发布的Event
事件:ContextRefreshedEvent
ApplicationReadyEvent
ApplicationStartedEvent
.....
- 使用 ApplicationRunner、CommandLineRunner
org.springframework.context.SmartLifecycle#start()
执行优先级 @PostConstruct > SmartLifecycle.start() > ContextRefreshedEvent > ApplicationStartedEvent >ApplicationRunner > CommandLineRunner > ApplicationReadyEvent
@PostConstruct
@PostConstruct 是 JavaEE中的注解,全路径:javax.annotation.PostConstruct
。
Spring 会在 bean 的初始化(afterPropertiesSet
)之后自动调用这个方法。通常用于执行初始化操作,例如连接资源、加载配置等。
官方注释:
The PostConstruct annotation is used on a method that needs to be executed after dependency injection is done to perform any initialization. This method must be invoked before the class is put into service. This annotation must be supported on all classes that support dependency injection.
PostConstruct 注解用于需要在完成依赖注入后执行以执行任何初始化的方法。在类投入使用之前,必须调用此方法。支持依赖项注入的所有类都必须支持此 Comments。
SmartLifecycle
SmartLifecycle
接口扩展了 Lifecycle
接口,具有自动启动和停止功能。start()
方法在应用程序启动时调用,通常用于启动和停止自定义组件,常用于管理后台任务、资源连接等。
isAutoStartup()
:返回是否自动启动,适用于需要延迟加载的组件。start()
:在容器启动时调用。stop()
:在容器关闭时调用。
Event
Spring 中在各个内部模块都有观察者模式的体现。简单介绍下跟本文相关的两个监听器:
-
ApplicationListener:是 Spring 中通用的事件监听器。主要用来监听 Spring 应用中的所有事件,包含框架内置和自定义的事件。比如:
ContextRefreshedEvent
:当应用上下文被刷新时发布。通常在@PostConstruct
之后调用,表示应用上下文已加载并完成初始化ApplicationReadyEvent
:表示应用已完全启动且准备就绪,可以接收请求。此事件在CommandLineRunner
和ApplicationRunner
执行之后发布,常用于表示应用的最终启动完成。ApplicationStartedEvent
:当应用启动且环境和上下文准备完成,但在CommandLineRunner
和ApplicationRunner
执行之前发布。可以用于执行在应用准备完成但未完全启动时的操作。
-
SpringApplicationRunListener:Spring Boot 内置的监听器,主要用于 SpringBoot 启动的整个过程。比如:初始化、环境准备、上下文准备和完全启动等多个阶段。
- starting():在 run 方法首次启动时立即调用。可用于非常早期的初始化。
- environmentPrepared():在准备好环境后但在创建环境之前 ApplicationContext 调用。
- contextPrepared():在创建并准备 之后 ApplicationContext ,但在加载源之前调用。
- contextLoaded():在加载应用程序上下文后但在刷新应用程序上下文之前调用。
- started():上下文已刷新,应用程序已启动,但CommandLineRunnersApplicationRunners尚未被调用。
- running():在 run 方法完成之前立即调用,此时应用程序上下文已刷新并且 all CommandLineRunners 和 ApplicationRunners 已被调用。
- failed():在运行应用程序时发生故障时调用。
上述方法都是 SpringApplicationRunListener 内置的方法。
ApplicationRunner、CommandLineRunner
两者都在Spring Boot应用启动完成且ApplicationContext
已被完全初始化之后执行。
CommandLineRunner
:实现此接口的 bean 会在ApplicationContext
启动并完成所有 bean 的初始化后调用,适合执行启动后的一些自定义任务。ApplicationRunner
:与CommandLineRunner
类似,但支持使用ApplicationArguments
作为参数,可以更方便地访问应用启动参数。