我想在我的spring-boot应用开始监视目录更改后运行代码。
我尝试运行新线程,但此时@Autowired
尚未设置服务。
我已经能够找到ApplicationPreparedEvent
,它会在设置@Autowired
注释之前触发。理想情况下,一旦应用程序准备处理http请求,我希望触发该事件。
在Spring Boot中启动应用程序后,是否有更好的事件可以使用,或者有更好的代码运行方式?
我想在我的spring-boot应用开始监视目录更改后运行代码。
我尝试运行新线程,但此时@Autowired
尚未设置服务。
我已经能够找到ApplicationPreparedEvent
,它会在设置@Autowired
注释之前触发。理想情况下,一旦应用程序准备处理http请求,我希望触发该事件。
在Spring Boot中启动应用程序后,是否有更好的事件可以使用,或者有更好的代码运行方式?
Answers:
尝试:
@Configuration
@EnableAutoConfiguration
@ComponentScan
public class Application extends SpringBootServletInitializer {
@SuppressWarnings("resource")
public static void main(final String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);
context.getBean(Table.class).fillWithTestdata(); // <-- here
}
}
@Component
。请参阅来自@cjstehno的答案,以使其在war文件中起作用。
就这么简单:
@EventListener(ApplicationReadyEvent.class)
public void doSomethingAfterStartup() {
System.out.println("hello world, I have just started up");
}
在版本上测试 1.5.1.RELEASE
@EventListener(ContextRefreshedEvent.class)
它,它在创建bean之后但在服务器启动之前被触发。它可以用于在任何请求到达服务器之前执行活动。
ContextRefreshedEvent
,它也会在每次刷新后运行。
您是否尝试过ApplicationReadyEvent?
@Component
public class ApplicationStartup
implements ApplicationListener<ApplicationReadyEvent> {
/**
* This event is executed as late as conceivably possible to indicate that
* the application is ready to service requests.
*/
@Override
public void onApplicationEvent(final ApplicationReadyEvent event) {
// here your code ...
return;
}
}
来自以下网址的代码:http://blog.netgloo.com/2014/11/13/run-code-at-spring-boot-startup/
这是文档中提到的有关启动事件的内容:
...
应用程序事件在您的应用程序运行时按以下顺序发送:
ApplicationStartedEvent在运行开始时发送,但在除侦听器和初始化程序的注册之外的任何处理之前发送。
当已知要在上下文中使用的环境时,但在创建上下文之前,将发送ApplicationEnvironmentPreparedEvent。
在刷新开始之前,但在加载bean定义之后,发送了ApplicationPreparedEvent。
刷新后,将发送ApplicationReadyEvent,并且已处理所有相关的回调,以指示应用程序已准备好处理请求。
如果启动时发生异常,则发送ApplicationFailedEvent。
...
@EventListener
在Bean方法上使用批注来执行此操作,将要钩住的类事件作为参数传递。
为什么不创建一个在初始化时启动监视器的Bean,例如:
@Component
public class Monitor {
@Autowired private SomeService service
@PostConstruct
public void init(){
// start your monitoring in here
}
}
init
直到对bean完成任何自动装配后,该方法才会被调用。
@PostConstruct
开火太早。例如,当使用Spring Cloud Stream Kafka时,@PostConstruct
在应用程序绑定到Kafka之前触发。Dave Syer的解决方案更好,因为它可以及时触发。
@PostConstruct
发生在初始化期间,而不是之后。尽管在某些情况下这很有用,但是如果您想在 Spring Boot启动后运行,那不是正确的答案。例如,虽然@PostConstruct
尚未完成,但没有端点可用。
“ Spring Boot”方法是使用CommandLineRunner
。只需添加这种类型的豆,就可以了。在Spring 4.1(Boot 1.2)中,还有SmartInitializingBean
一个在所有初始化之后获得回调的函数。还有SmartLifecycle
(从Spring 3开始)。
CommandLineRunner
(和较新版本ApplicationRunner
)的示例:docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/…。
CommandLineRunner
您可以使用扩展类ApplicationRunner
,覆盖run()
方法并在其中添加代码。
import org.springframework.boot.ApplicationRunner;
@Component
public class ServerInitializer implements ApplicationRunner {
@Override
public void run(ApplicationArguments applicationArguments) throws Exception {
//code goes here
}
}
ApplicationReadyEvent
仅在您要执行的任务不需要正确的服务器操作时才真正有用。启动异步任务以监视某些内容的更改就是一个很好的例子。
但是,如果您的服务器在任务完成之前处于“未就绪”状态,则最好实施,SmartInitializingSingleton
因为您将在获得回调之前在打开REST端口和服务器开始营业。
不要试图将@PostConstruct
其仅执行一次。当您发现它被多次调用时,您会得到一个粗鲁的惊喜……
提供一个Dave Syer答案的示例,它的工作原理很吸引人:
@Component
public class CommandLineAppStartupRunner implements CommandLineRunner {
private static final Logger logger = LoggerFactory.getLogger(CommandLineAppStartupRunner.class);
@Override
public void run(String...args) throws Exception {
logger.info("Application started with command-line arguments: {} . \n To kill this application, press Ctrl + C.", Arrays.toString(args));
}
}
我真的很喜欢EventListener
@cahen(https://stackoverflow.com/a/44923402/9122660)关于使用注释的建议,因为它非常干净。不幸的是,我无法在Spring + Kotlin设置中使用它。对于Kotlin起作用的是将类添加为方法参数:
@EventListener
fun doSomethingAfterStartup(event: ApplicationReadyEvent) {
System.out.println("hello world, I have just started up");
}
@SpringBootApplication class MyApplication { @EventListener(ApplicationReadyEvent::class) fun doSomethingAfterStartup() { println("hello world, I have just started up") } }
在Spring Boot应用程序启动后执行代码块的最佳方法是使用PostConstruct批注,或者也可以使用命令行运行器。
1.使用PostConstruct批注
@Configuration
public class InitialDataConfiguration {
@PostConstruct
public void postConstruct() {
System.out.println("Started after Spring boot application !");
}
}
2.使用命令行流道bean
@Configuration
public class InitialDataConfiguration {
@Bean
CommandLineRunner runner() {
return args -> {
System.out.println("CommandLineRunner running in the UnsplashApplication class...");
};
}
}
使用CommandLineRunner或ApplicationRunner的最佳方法两者之间的唯一区别是run()方法CommandLineRunner接受字符串数组,而ApplicationRunner接受ApplicationArugument。