Spring 启动时不能按顺序运行 几个方法
Can not run few methods sequentially when Spring Boot starts
当应用程序启动时,我必须运行一些方法,如下所示:
@SpringBootApplication
public class Application implements CommandLineRunner {
private final MonitoringService monitoringService;
private final QrReaderServer qrReaderServer;
@Override
public void run(String... args) {
monitoringService.launchMonitoring();
qrReaderServer.launchServer();
}
但是,只执行了第一个!并启动应用程序:
... Started Application in 5.21 seconds (JVM running for 6.336)
... START_MONITORING for folder: D:\results
总是跳过第二个!
如果更改调用顺序 - 只有第二个会被执行。
一开始找不到启动两者的解决方案 - 尝试了 @PostConstruct
、ApplicationRunner
、@EventListener(ApplicationReadyEvent.class)
...
看起来他们以某种方式互相阻挡。尽管 都是 void 类型 .
监控启动实施:
@Override
public void launchMonitoring() {
log.info("START_MONITORING for folder: {}", monitoringProperties.getFolder());
try {
WatchKey key;
while ((key = watchService.take()) != null) {
for (WatchEvent<?> event : key.pollEvents()) {
WatchEvent.Kind<?> kind = event.kind();
if (kind == ENTRY_CREATE) {
log.info("FILE_CREATED: {}", event.context());
// some delay for fully file upload
Thread.sleep(monitoringProperties.getFrequency());
String fullFileName = getFileName(event);
String fileName = FilenameUtils.removeExtension(fullFileName);
processResource(fullFileName, fileName);
}
}
key.reset();
}
} catch (InterruptedException e) {
log.error("interrupted exception for monitoring service", e);
} catch (IOException e) {
log.error("io exception while processing file", e);
}
}
QR Reader 启动(使用 Netty 配置启动 TCP 服务器):
@Override
public void launchServer() {
try {
ChannelFuture serverChannelFuture = serverBootstrap.bind(hostAddress).sync();
log.info("Server is STARTED : port {}", hostAddress.getPort());
serverChannel = serverChannelFuture.channel().closeFuture().sync().channel();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
shutdownQuietly();
}
}
如何解决这个问题?
异步启动 launchMonitoring()
。
最简单的方法是通过在您的应用程序中添加 @EnableAsync
来启用异步
然后用 @Async
注释 launchMonitoring()
不确定 launchServer()
是否也应该异步启动。
编辑:完成答案
No task executor bean found for async processing: no bean of type TaskExecutor and no bean named 'taskExecutor' either
默认情况下Spring会创建一个SimpleAsyncTaskExecutor
,但是你可以提供你的taskExecutor
示例:
@EnableAsync
@Configuration
public class AsyncConfig implements AsyncConfigurer {
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.set... // your custom configs
executor.initialize();
return executor;
}
...
}
当应用程序启动时,我必须运行一些方法,如下所示:
@SpringBootApplication
public class Application implements CommandLineRunner {
private final MonitoringService monitoringService;
private final QrReaderServer qrReaderServer;
@Override
public void run(String... args) {
monitoringService.launchMonitoring();
qrReaderServer.launchServer();
}
但是,只执行了第一个!并启动应用程序:
... Started Application in 5.21 seconds (JVM running for 6.336)
... START_MONITORING for folder: D:\results
总是跳过第二个!
如果更改调用顺序 - 只有第二个会被执行。
一开始找不到启动两者的解决方案 - 尝试了 @PostConstruct
、ApplicationRunner
、@EventListener(ApplicationReadyEvent.class)
...
看起来他们以某种方式互相阻挡。尽管 都是 void 类型 .
监控启动实施:
@Override
public void launchMonitoring() {
log.info("START_MONITORING for folder: {}", monitoringProperties.getFolder());
try {
WatchKey key;
while ((key = watchService.take()) != null) {
for (WatchEvent<?> event : key.pollEvents()) {
WatchEvent.Kind<?> kind = event.kind();
if (kind == ENTRY_CREATE) {
log.info("FILE_CREATED: {}", event.context());
// some delay for fully file upload
Thread.sleep(monitoringProperties.getFrequency());
String fullFileName = getFileName(event);
String fileName = FilenameUtils.removeExtension(fullFileName);
processResource(fullFileName, fileName);
}
}
key.reset();
}
} catch (InterruptedException e) {
log.error("interrupted exception for monitoring service", e);
} catch (IOException e) {
log.error("io exception while processing file", e);
}
}
QR Reader 启动(使用 Netty 配置启动 TCP 服务器):
@Override
public void launchServer() {
try {
ChannelFuture serverChannelFuture = serverBootstrap.bind(hostAddress).sync();
log.info("Server is STARTED : port {}", hostAddress.getPort());
serverChannel = serverChannelFuture.channel().closeFuture().sync().channel();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
shutdownQuietly();
}
}
如何解决这个问题?
异步启动 launchMonitoring()
。
最简单的方法是通过在您的应用程序中添加 @EnableAsync
来启用异步
然后用 @Async
launchMonitoring()
不确定 launchServer()
是否也应该异步启动。
编辑:完成答案
No task executor bean found for async processing: no bean of type TaskExecutor and no bean named 'taskExecutor' either
默认情况下Spring会创建一个SimpleAsyncTaskExecutor
,但是你可以提供你的taskExecutor
示例:
@EnableAsync
@Configuration
public class AsyncConfig implements AsyncConfigurer {
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.set... // your custom configs
executor.initialize();
return executor;
}
...
}