SpringBoot 怎么做到在 web 容器启动之前做点 xx 事情?

2023-03-13 11:49:58 +08:00
 leegoo

目前有很多初始化方法都实现了 org.springframework.boot.ApplicationRunner#run ,同时该应用也提供了 web 功能。

目前发现一个问题。该应用在没有完全执行完 org.springframework.boot.ApplicationRunner#run 方法后就会可以访问 HTTP 接口。导致接口响应结果与实际业务结果不符。

查询了一下初始化方法类可以实现ApplicationPreparedEvent接口,确实在 Web 容器启动前调用了。但是不能获取到bean

想问下大家还有其他的方式吗。

2067 次点击
所在节点    程序员
9 条回复
javahuang
2023-03-13 12:23:28 +08:00
@EventListener(ApplicationReadyEvent.class)
话说这种问题不是 google 来的更快吗
selca
2023-03-13 12:28:06 +08:00
```java
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);

StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);

// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
beanPostProcess.end();

// Initialize message source for this context.
initMessageSource();

// Initialize event multicaster for this context.
initApplicationEventMulticaster();

// Initialize other special beans in specific context subclasses.
onRefresh();

// Check for listener beans and register them.
registerListeners();

// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);

// Last step: publish corresponding event.
finishRefresh();
```
看了下,web 容器在 onRefresh()阶段初始化的,可以看下这里前几个阶段有没有可以操作的
lry
2023-03-13 13:03:03 +08:00
需要做的事情是啥?需要拿到什么 bean ?
通用的可以试试当做完事情之后再注册服务
anc95
2023-03-13 13:13:49 +08:00
可以通过实现 Spring 的接口 org.springframework.boot.ApplicationRunner 或 org.springframework.boot.CommandLineRunner 来在 web 容器启动之前执行一些操作。这些接口的实现类会在 Spring Boot 应用启动时被自动运行。

ApplicationRunner 的 run() 方法会在 Spring 应用启动完成后被调用,而 CommandLineRunner 的 run(String... args) 方法会在 Spring 应用启动时被调用,这两个接口的返回值类型都是 void 。

例如,以下代码实现了一个 CommandLineRunner 接口:

@Component
public class MyCommandLineRunner implements CommandLineRunner {

@Override
public void run(String... args) throws Exception {
System.out.println("执行 MyCommandLineRunner");
}
}
当 Spring Boot 应用启动时,MyCommandLineRunner 中的 run() 方法会被调用,并输出 执行 MyCommandLineRunner 。
leegoo
2023-03-13 14:02:06 +08:00
@javahuang 谢谢你的答案,我试了一下在 META-INF/spring.factories 添加了`org.springframework.context.ApplicationListener=xxxListener`
`xxxListener 类里面实现了 ApplicationListener<ApplicationReadyEvent>`。SpringBoot 启动时可以调到`xxxListener`类,不过依然获取不到 bean 对象
leegoo
2023-03-13 14:04:28 +08:00
获取应该说。在 xxxListener 执行时。controller 已经提前执行了。
shellic
2023-03-13 14:26:37 +08:00
WebServerInitializedEvent
cheng6563
2023-03-13 15:06:57 +08:00
直接 @PostConstruct 就行了啊
ThreeK
2023-03-13 15:56:22 +08:00
建议直接百度张 spring boot 注入启动的流程图,确定下自己的代码想何时触发,然后再看自己需要实现那个钩子函数就行。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/923544

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX