web-dev-qa-db-fra.com

Exécution du code après le démarrage de Spring Boot

Je veux exécuter du code après que mon spring-boot app commence à surveiller un répertoire pour y apporter des modifications. 

J'ai essayé de lancer un nouveau thread, mais les services @Autowired n'ont pas encore été définis.

J'ai pu trouver ApplicationPreparedEvent, qui se déclenche avant que les annotations @Autowired ne soient définies. Idéalement, j'aimerais que l'événement se déclenche une fois que l'application est prête à traiter les requêtes http.

Existe-t-il un meilleur événement à utiliser ou un meilleur moyen d’exécuter du code une fois l’application installée dans spring-boot ?

118
stewsters

Essayer:

@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
    }
}
79
Anton Bessonov

C'est aussi simple que cela: 

@EventListener(ApplicationReadyEvent.class)
public void doSomethingAfterStartup() {
    System.out.println("hello world, I have just started up");
}

Testé sur la version 1.5.1.RELEASE

165
cahen

Avez-vous essayé 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;
  }
}

Code de: http://blog.netgloo.com/2014/11/13/run-code-at-spring-boot-startup/

Voici ce que la documentation mentionne à propos des événements de démarrage:

...

Les événements d'application sont envoyés dans l'ordre suivant, au cours de l'exécution de votre application:

Un ApplicationStartedEvent est envoyé au début d'une exécution, mais avant tout traitement sauf l'enregistrement des écouteurs et des initialiseurs.

Un ApplicationEnvironmentPreparedEvent est envoyé lorsque l'environnement à utiliser dans le contexte est connu, mais avant le contexte est créé.

Un événement ApplicationPreparedEvent est envoyé juste avant le démarrage de l'actualisation, mais après le chargement des définitions de bean.

Un événement ApplicationReadyEvent est envoyé après l'actualisation et tous les rappels associés ont été traités pour indiquer que l'application est prête à utiliser demandes de service.

Un ApplicationFailedEvent est envoyé s'il existe une exception au démarrage.

...

76
raspacorp

Pourquoi ne pas simplement créer un haricot qui démarre votre moniteur à l’initialisation, quelque chose comme:

@Component
public class Monitor {
    @Autowired private SomeService service

    @PostConstruct
    public void init(){
        // start your monitoring in here
    }
}

la méthode init ne sera pas appelée tant que le câblage automatique n'aura pas été effectué pour le bean.

76
cjstehno

La méthode "Spring Boot" consiste à utiliser une variable CommandLineRunner. Ajoutez simplement des haricots de ce type et vous êtes prêt à partir. Dans Spring 4.1 (Boot 1.2), il existe également une SmartInitializingBean qui reçoit un rappel une fois que tout est initialisé. Et il y a SmartLifecycle (à partir du printemps 3).

57
Dave Syer

Vous pouvez étendre une classe en utilisant ApplicationRunner , substituer la méthode run() et ajouter le code à cet endroit. 

import org.springframework.boot.ApplicationRunner;

@Component
public class ServerInitializer implements ApplicationRunner {

    @Override
    public void run(ApplicationArguments applicationArguments) throws Exception {

        //code goes here

    }
}
29
Gimhani

ApplicationReadyEvent n'est utile que si la tâche que vous voulez effectuer n'est pas une condition requise pour un fonctionnement correct du serveur. Démarrer une tâche asynchrone pour surveiller quelque chose pour des modifications est un bon exemple.

Si, toutefois, votre serveur est dans un état "pas prêt" jusqu'à la fin de la tâche, il est préférable d'implémenter SmartInitializingSingleton car vous obtiendrez le rappel avant votre port REST a été ouvert et votre serveur Ouvert pour les affaires.

Ne soyez pas tenté d'utiliser @PostConstruct pour des tâches qui ne devraient se produire qu'une seule fois. Vous aurez une surprise désagréable lorsque vous remarquerez qu'il est appelé plusieurs fois ...

15
Andy Brown

Avec configuration à ressort:

@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");
  }
}
15
freemanpolys

Utilisez un haricot SmartInitializingSingleton au printemps> 4.1

@Bean
public SmartInitializingSingleton importProcessor() {
    return () -> {
        doStuff();
    };

}

Comme alternative, un bean CommandLineRunner peut être implémenté ou annoter une méthode de bean avec @PostConstruct.

9
Jeff

Voici un exemple de réponse de Dave Syer, qui a fonctionné à merveille:

@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));
    }
}
3
Paulo Pedroso

il suffit d'implémenter CommandLineRunner pour une application de démarrage printanier . Vous devez implémenter une méthode d'exécution,

public classs SpringBootApplication implements CommandLineRunner{

    @Override
        public void run(String... arg0) throws Exception {
        // write your logic here 

        }
}
1
prasad kp

Essayez celui-ci et il exécutera votre code lorsque le contexte de l'application aura complètement démarré.

 @Component
public class OnStartServer implements ApplicationListener<ContextRefreshedEvent> {

    @Override
    public void onApplicationEvent(ContextRefreshedEvent arg0) {
                // EXECUTE YOUR CODE HERE 
    }
}
1
Kalifornium

Le meilleur moyen d'exécuter un bloc de code après le démarrage de l'application Spring Boot consiste à utiliser annotation PostConstruct. Vous pouvez également utiliser le programme d'exécution de ligne de commande pour la même chose.

1. Utilisation de l'annotation PostConstruct

@Configuration
public class InitialDataConfiguration {

    @PostConstruct
    public void postConstruct() {
        System.out.println("Started after Spring boot application !");
    }

}

2. Utilisation du haricot de la ligne de commande

@Configuration
public class InitialDataConfiguration {

    @Bean
    CommandLineRunner runner() {
        return args -> {
            System.out.println("CommandLineRunner running in the UnsplashApplication class...");
        };
    }
}
0
Naresh

J'aime beaucoup la suggestion d'utilisation de l'annotation EventListener par @cahen ( https://stackoverflow.com/a/44923402/9122660 ) car elle est très propre. Malheureusement, je ne pouvais pas obtenir que cela fonctionne dans une configuration Spring + Kotlin. Ce qui fonctionne pour Kotlin ajoute la classe en tant que paramètre de méthode:

@EventListener 
fun doSomethingAfterStartup(event: ApplicationReadyEvent) {
    System.out.println("hello world, I have just started up");
}
0
Ostecke