普通Java应用转Spring Boot:启动时调用含ExecutorService的method()
嘿,我来帮你搞定把普通Java应用转成Spring Boot,并且在启动时调用A类method()的问题!这里有几种实用的方式,你可以根据自己的场景选择:
先做个小准备:把A类和线程池交给Spring管理
首先建议你把原来的A类注册成Spring Bean,并且让Spring管理线程池(避免手动创建导致资源泄漏),调整后的A类大概是这样:
import org.springframework.stereotype.Component; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import javax.annotation.PreDestroy; @Component public class A { // 根据你的实际需求选择线程池类型,这里用固定线程池示例 private final ExecutorService executorService = Executors.newFixedThreadPool(5); public void method() { // 注意这里要传入Runnable实例,原代码里的MyRunnableClass要new出来 executorService.execute(new MyRunnableClass()); } // 优雅关闭线程池,避免Spring Boot关闭时残留线程 @PreDestroy public void shutdownExecutor() { executorService.shutdown(); try { if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) { executorService.shutdownNow(); } } catch (InterruptedException e) { executorService.shutdownNow(); Thread.currentThread().interrupt(); } } } // 你的MyRunnableClass实现Runnable接口 class MyRunnableClass implements Runnable { @Override public void run() { // 这里写你的业务逻辑 System.out.println("执行MyRunnableClass的run方法"); } }
方法1:用CommandLineRunner(最常用)
Spring Boot提供的CommandLineRunner接口会在Spring上下文完全加载完成后自动执行run方法,非常适合启动时执行初始化逻辑:
import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Component; @Component public class StartupRunner implements CommandLineRunner { private final A a; // 构造注入A类的Bean实例 public StartupRunner(A a) { this.a = a; } @Override public void run(String... args) throws Exception { // 启动时调用method() a.method(); } }
方法2:用ApplicationRunner(适合处理命令行参数)
和CommandLineRunner几乎一样,只是接收的参数是ApplicationArguments,能更方便地解析命令行参数:
import org.springframework.boot.ApplicationRunner; import org.springframework.boot.ApplicationArguments; import org.springframework.stereotype.Component; @Component public class StartupAppRunner implements ApplicationRunner { private final A a; public StartupAppRunner(A a) { this.a = a; } @Override public void run(ApplicationArguments args) throws Exception { a.method(); // 如果需要处理命令行参数,可以用args.getOptionNames()等方法 } }
方法3:用@PostConstruct(Bean初始化时执行)
如果你的A类本身就是Spring Bean,也可以直接在类里加一个初始化方法,用@PostConstruct标记,它会在Bean创建完成后执行:
import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import javax.annotation.PreDestroy; @Component public class A { private final ExecutorService executorService = Executors.newFixedThreadPool(5); // 标记这个方法在Bean初始化后执行 @PostConstruct public void onStartup() { method(); } public void method() { executorService.execute(new MyRunnableClass()); } @PreDestroy public void shutdownExecutor() { // 线程池关闭逻辑同上 executorService.shutdown(); try { if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) { executorService.shutdownNow(); } } catch (InterruptedException e) { executorService.shutdownNow(); Thread.currentThread().interrupt(); } } }
小提示
- 优先选
CommandLineRunner或ApplicationRunner,因为它们是在整个Spring上下文加载完成后执行,不会出现依赖Bean还没初始化的问题; - 一定要记得给线程池加关闭逻辑(
@PreDestroy里的代码),不然Spring Boot关闭时可能会有线程残留,导致应用无法正常退出。
内容的提问来源于stack exchange,提问作者Megan
相关产品推荐
相关产品推荐

