我在Tomcat 8中部署了一个Spring Boot应用程序。当应用程序启动时,我想在Spring Autowires的后台启动一个具有一些依赖关系的工作线程。目前我有这个:
@SpringBootApplication
@EnableAutoConfiguration
@ComponentScan
public class MyServer extends SpringBootServletInitializer {
public static void main(String[] args) {
log.info("Starting application");
ApplicationContext ctx = SpringApplication.run(MyServer.class, args);
Thread subscriber = new Thread(ctx.getBean(EventSubscriber.class));
log.info("Starting Subscriber Thread");
subscriber.start();
}
在我的Docker测试环境中,这很好用 - 但是当我将它部署到Tomcat 8中的Linux(Debian Jessie,Java 8)主机时,我从未看到“Starting Subscriber Thread”消息(并且线程未启动)
答案 0 :(得分:7)
将应用程序部署到非嵌入式应用程序服务器时,不会调用main方法。 启动线程的最简单方法是从beans构造函数中执行此操作。 在上下文关闭时清理线程也是一个好主意,例如:
@Component
class EventSubscriber implements DisposableBean, Runnable {
private Thread thread;
private volatile boolean someCondition;
EventSubscriber(){
this.thread = new Thread(this);
this.thread.start();
}
@Override
public void run(){
while(someCondition){
doStuff();
}
}
@Override
public void destroy(){
someCondition = false;
}
}
答案 1 :(得分:3)
你可以拥有一个bean ApplicationListener<ContextRefreshedEvent>
onApplicationEvent
只要它尚未启动就会调用它@Component
public class FooBar implements ApplicationListener<ContextRefreshedEvent> {
Thread t = new Thread();
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
if (!t.isAlive()) {
t.start();
}
}
}
。我想你顺便想要ApplicationReadyEvent。
修改强> How to add a hook to the application context initialization event?
Regex Pattern -- [([^]]*])
Input String -- [blue][red][green]
Output -- 1st match --->[blue]
2nd match --->[red]
3rd match --->[green]
答案 2 :(得分:0)
手动启动线程可能不是最好的方法。而是使用 Springs Task execution and Scheduling 功能。