java - starter - Ejecución de código después de que comience Spring Boot
spring boot wikipedia (14)
¿Has probado 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;
}
}
Código de: http://blog.netgloo.com/2014/11/13/run-code-at-spring-boot-startup/
Esto es lo documentation menciona la documentation sobre los eventos de inicio:
...
Los eventos de la aplicación se envían en el siguiente orden, a medida que se ejecuta la aplicación:
Un ApplicationStartedEvent se envía al comienzo de una ejecución, pero antes de cualquier procesamiento, excepto el registro de oyentes e inicializadores.
Un ApplicationEnvironmentPreparedEvent se envía cuando se conoce el entorno que se utilizará en el contexto, pero antes de que se cree el contexto.
Se envía un ApplicationPreparedEvent justo antes de que se inicie la actualización, pero después de que se hayan cargado las definiciones de bean.
Se envía un ApplicationReadyEvent después de la actualización y se han procesado las devoluciones de llamada relacionadas para indicar que la aplicación está lista para atender las solicitudes.
Se envía un ApplicationFailedEvent si hay una excepción al inicio.
...
Quiero ejecutar el código después de que mi aplicación spring-boot comience a monitorear un directorio para detectar cambios.
He intentado ejecutar un nuevo hilo pero los servicios
@Autowired
no se han establecido en ese punto.
He podido encontrar
ApplicationPreparedEvent
, que se
@Autowired
antes de que se
@Autowired
anotaciones
@Autowired
.
Idealmente, me gustaría que el evento se active una vez que la aplicación esté lista para procesar solicitudes http.
¿Hay un mejor evento para usar, o una mejor manera de ejecutar el código después de que la aplicación esté activa en spring-boot ?
¿Por qué no simplemente crear un bean que inicia su monitor en la inicialización, algo como:
@Component
public class Monitor {
@Autowired private SomeService service
@PostConstruct
public void init(){
// start your monitoring in here
}
}
el método
init
no se llamará hasta que se realice un cableado automático para el bean.
Con configuración de resorte:
@Configuration
public class ProjectConfiguration {
private static final Logger log =
LoggerFactory.getLogger(ProjectConfiguration.class);
@EventListener(ApplicationReadyEvent.class)
public void doSomethingAfterStartup() {
log.info("hello world, I have just started up");
}
}
Es tan simple como esto:
@EventListener(ApplicationReadyEvent.class)
public void doSomethingAfterStartup() {
System.out.println("hello world, I have just started up");
}
Probado en la versión
1.5.1.RELEASE
La forma de "Spring Boot" es usar un
CommandLineRunner
.
Solo agregue frijoles de ese tipo y estará listo.
En Spring 4.1 (Boot 1.2) también hay un
SmartInitializingBean
que recibe una devolución de llamada después de que todo se haya inicializado.
Y hay
SmartLifecycle
(de Spring 3).
La mejor manera de ejecutar el bloque de código después de que se inicie la aplicación Spring Boot es usando la anotación PostConstruct, o también puede usar el corredor de línea de comando para el mismo.
1. Usando la anotación PostConstruct
@Configuration
public class InitialDataConfiguration {
@PostConstruct
public void postConstruct() {
System.out.println("Started after Spring boot application !");
}
}
2. Usando la línea de comando Bean Runner
@Configuration
public class InitialDataConfiguration {
@Bean
CommandLineRunner runner() {
return args -> {
System.out.println("CommandLineRunner running in the UnsplashApplication class...");
};
}
}
Proporcionando un ejemplo para la respuesta de Dave Syer, que funcionó a las mil maravillas:
@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));
}
}
Pruebe este y ejecutará su código cuando el contexto de la aplicación se haya iniciado por completo.
@Component
public class OnStartServer implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent arg0) {
// EXECUTE YOUR CODE HERE
}
}
Puede extender una clase usando
ApplicationRunner
, anular el método
run()
y agregar el código allí.
import org.springframework.boot.ApplicationRunner;
@Component
public class ServerInitializer implements ApplicationRunner {
@Override
public void run(ApplicationArguments applicationArguments) throws Exception {
//code goes here
}
}
Realmente me gusta la sugerencia para el uso de la anotación EventListener por @cahen ( https://.com/a/44923402/9122660 ) ya que está muy limpia. Lamentablemente, no pude hacer que esto funcionara en una configuración Spring + Kotlin. Lo que sí funciona para Kotlin es agregar la clase como parámetro de método:
@EventListener
fun doSomethingAfterStartup(event: ApplicationReadyEvent) {
System.out.println("hello world, I have just started up");
}
Tratar:
@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
}
}
Use un
SmartInitializingSingleton
bean en primavera> 4.1
@Bean
public SmartInitializingSingleton importProcessor() {
return () -> {
doStuff();
};
}
Como alternativa, se puede implementar un bean
CommandLineRunner
o anotar un método de bean con
@PostConstruct
.
simplemente implemente CommandLineRunner para la aplicación de arranque de primavera. Necesita implementar el método de ejecución,
public classs SpringBootApplication implements CommandLineRunner{
@Override
public void run(String... arg0) throws Exception {
// write your logic here
}
}
ApplicationReadyEvent
solo es realmente útil si la tarea que desea realizar no es un requisito para el correcto funcionamiento del servidor.
Iniciar una tarea asincrónica para monitorear algo en busca de cambios es un buen ejemplo.
Sin embargo, si su servidor está en un estado ''no listo'' hasta que se complete la tarea, entonces es mejor implementar
SmartInitializingSingleton
porque recibirá la devolución de llamada
antes de que
su puerto REST se haya abierto y su servidor esté abierto para los negocios.
No
@PostConstruct
tentación de utilizar
@PostConstruct
para tareas que solo deberían ocurrir una vez.
Obtendrá una sorpresa grosera cuando note que se llama varias veces ...