在springboot的项目中,需要在容器启动之后执行一些操作,springboot提供了ApplicationRunner和CommandLineRunner两个接口,按理说可以帮助我们实现这种需求。但在项目里有两个程序实现了ApplicationRunner接口,并将逻辑代码分别放在了run()方法里,实际只能运行起来一个程序.
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
import javax.annotation.PreDestroy;
import java.util.concurrent.atomic.AtomicBoolean;
@Slf4j
@Component
public class AutoProcess implements ApplicationRunner {
public static final AtomicBoolean isRunning = new AtomicBoolean(true);
@Override
public void run(ApplicationArguments args) throws Exception {
while (isRunning.get()) {
try{
// 逻辑代码
}catch (Exception e) {
log.error("处理异常", e);
}finally {
// ...
}
}
if(!isRunning.get()){
// ...
}
}
@PreDestroy
public void close(){
isRunning.set(false);
}
}
通过分析springboot启动的源码可以发现,在applicationContext容器加载完成之后,会调用SpringApplication类的callRunners方法,该方法中会获取所有实现了ApplicationRunner和CommandLineRunner的接口bean,然后依次执行对应的run方法,并且是在同一个线程中执行。因此如果有某个实现了ApplicationRunner接口的bean的run方法一直循环不返回的话,后续的代码将不会被执行。
1.让主程序启动后自动执行的类继承抽象类Thread(多线程方式)同时实现run()方法,将逻辑代码放在该方法中
2.通过@Bean注解将要启动的类注入到容器中,并指明容器初始化Bean和销毁前所执行的方法,initMethod = “start”意味着调用Thread对象的start()方法,即启动线程,它会隐含的调用run()方法即我们的逻辑代码.
1.继承Thread,编写逻辑代码
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.annotation.PreDestroy;
import java.util.concurrent.atomic.AtomicBoolean;
@Slf4j
@Component
public class AutoProcess extends Thread {
public static final AtomicBoolean isRunning = new AtomicBoolean(true);
@Override
public void run() {
while (isRunning.get()) {
try{
// 逻辑代码
}catch (Exception e) {
log.error("处理异常", e);
}finally {
// ...
}
}
if(!isRunning.get()){
// ...
}
}
@PreDestroy
public void close(){
isRunning.set(false);
}
}
2.注入到容器,指明初始化方法
@Bean(initMethod = "start",destroyMethod = "close")
public AutoProcess autoProcess (){
AutoProcess autoProcess = new AutoProcess ();
return autoProcess;
}
记得点赞收藏奥,后续开发遇到问题会实时更新,关注不迷路~