学习如何进入应用程序引导生命周期并在Spring Boot启动时执行代码
1. Bean初始化时执行方法
Spring启动您的应用程序后,运行某些逻辑的最简单方法是将代码作为所选bean引导过程的一部分执行。
你要做什么
@PostConstruct批注的方法中即可。 从理论上讲,您可以使用构造函数代替单独的方法,但是将对象的构造与其实际职责分开是一种很好的做法。
@Component
class AppInitializator {
private static final Logger log = LoggerFactory.getLogger(AppInitializator.class);
@PostConstruct
private void init() {
log.info("AppInitializator initialization logic ...");
// ...
}
}
如果您使用应用程序上下文的延迟初始化(例如, 加快Spring Boot的启动速度 ),则应从此机制中排除具有初始化逻辑的bean。 我已经描述了当整个Spring上下文使用延迟加载时如何使用@Lazy批注快速创建bean 。
@PostConstruct批注创建方法。 不要忘记,主类也是由框架管理的组件。
@SpringBootApplication
public class InitDemoApplication {
// ...
@PostConstruct
private void init() {
log.info("InitDemoApplication initialization logic ...");
// ...
}
}
但是,此解决方案似乎是一种解决方法,而不是真正的解决方案。 您可以以非常有限的方式控制Spring框架创建应用程序Bean的顺序。 如果我们想在创建所有bean之前或者甚至在框架启动之前运行初始化逻辑,我们需要找到更好的方法。
2. Spring Boot启动挂钩
使用Spring Boot创建的应用程序的美妙之处在于,运行它们唯一需要的就是Java Runtime Environment和命令行界面。 无需外部工具或应用程序。 它像常规的Java SE程序一样运行。
与每个Java程序一样,您可以在输入应用程序类的static主方法中开始执行此类应用程序。 这就是您可以挂入Spring Boot初始化过程的关键所在。
创建Spring Boot钩子
首先在您的main方法中更改代码,以提取启动钩子到单独方法的附加内容。 您应该在启动应用程序之前添加Spring Boot挂钩。
public static void main(String[] args) {
SpringApplication application = new SpringApplication(InitDemoApplication.class);
addInitHooks(application);
application.run(args);
}
static void addInitHooks(SpringApplication application) {
// TBD …
}
当Spring Boot应用程序启动时,它将在引导过程的各个步骤上发布几个事件。 SpringApplication类的API公开了一个方法,我们可以使用该方法为这些事件添加侦听器。
这是一个示例,该示例在Spring上下文开始创建bean之前对发布的事件运行启动方法:
static void addInitHooks(SpringApplication application) {
application.addListeners((ApplicationListener<ApplicationEnvironmentPreparedEvent>) event -> {
String version = event.getEnvironment().getProperty("java.runtime.version");
log.info("Running with Java {}", version);
});
}
活动类型
根据事件类型 ,Spring传递给侦听器的对象可能使您可以访问一些有用的操作。 在前面的示例中,我们读取了一些环境属性,但也可以根据需要对其进行修改。
这是可能的事件的列表,按Spring Boot在启动时发布事件的顺序排序:
- ApplicationStartingEvent
- ApplicationEnvironmentPreparedEvent
- ApplicationContextInitializedEvent
- ApplicationPreparedEvent
- ApplicationStartedEvent
- ApplicationReadyEvent
我不想重复事件的文档,因此,如果您对事件描述感兴趣,就应该检查一下。 也有ApplicationFailedEvent,但仅在框架无法启动您的应用程序时才发布。
最重要的事件是ApplicationEnvironmentPreparedEvent 。 在Spring Boot启动的这一刻,还没有创建bean,但是您可以访问整个应用程序配置。 通常,这是运行一些自定义启动代码的最佳时机。
3.在没有嵌入式Tomcat的情况下在启动时运行代码
尽管Spring Boot设计人员在创建框架时就考虑了构建胖JAR的问题,但一些开发人员仍将Spring Boot应用程序部署到常规的servlet容器(例如Tomcat)。 如果是这种情况,那么如果没有其他步骤,上一段中的解决方案将无法工作。
如果将应用程序部署为常规WAR文件 ,则可能已经具有SpringBootServlerInitializator的自定义实现。 您只需稍微扩展它,并在应用程序构建过程中添加初始化钩子即可。
addInitHooks()方法。
public class InitDemoWarInitializer extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
InitDemoApplication.addInitHooks(builder.application());
return builder.sources(InitDemoApplication.class);
}
}
结论
简而言之,在Spring Boot启动时有两个主要选项来运行代码。 最简单的方法是初始化一个特定的bean。 对于更全球化的情况,该框架具有专用的解决方案,可以使用事件监听器进入其生命周期。 我们学习了如何实现和设置此类侦听器。
希望您觉得该帖子对您有所帮助。 您可以在我的Github存储库中找到可以正常运行的演示 。 我很高兴看到您对需要自定义钩子的用例的评论。 那应该使阅读有趣。
https://www.javacodegeeks.com/2018/11/running-code-spring-boot-startup.html