Exécuter la méthode au démarrage au printemps

Est-il un Printemps 3 fonctionnalité pour exécuter certaines méthodes lorsque l'application démarre pour la première fois? Je sais que je peux faire l'astuce de configurer une méthode avec @Scheduled annotation et il exécute juste après le démarrage, mais alors il exécutera périodiquement.

151
demandé sur Lonely Neuron 2010-03-08 16:16:28

11 réponses

si par" application startup "vous voulez dire" application context startup", alors oui, il y a de nombreuses façons de faire , la plus facile (pour singletons beans, anyway) étant d'annoter votre méthode avec @PostConstruct . Jetez un oeil sur le lien pour voir les autres options, mais en résumé:

  • méthodes annotées de @PostConstruct
  • afterPropertiesSet() tel que défini par l'interface de rappel InitializingBean
  • personnalisé configuré méthode init ()

techniquement, ce sont des crochets dans le bean cycle de vie, plutôt que le contexte cycle de vie, mais dans 99% des cas, les deux sont équivalents.

si vous devez vous connecter spécifiquement dans le contexte démarrage/arrêt, alors vous pouvez implémenter l'interface Lifecycle 151970920" à la place, mais c'est probablement inutile.

168
répondu skaffman 2012-01-13 18:24:54

cela se fait facilement avec un ApplicationListener . J'ai eu ça pour travailler en écoutant le ContextRefreshedEvent de Spring:

import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;

@Component
public class StartupHousekeeper implements ApplicationListener<ContextRefreshedEvent> {

  @Override
  public void onApplicationEvent(final ContextRefreshedEvent event) {
    // do whatever you need here 
  }
}
Les auditeurs de L'Application

fonctionnent de façon synchrone au printemps. Si vous voulez vous assurer que votre code n'est exécuté qu'une seule fois, gardez un État dans votre component.

mise à JOUR

à partir du printemps 4.2+ vous pouvez également utiliser l'annotation @EventListener pour observer le ContextRefreshedEvent (merci à @bphilipnyc pour avoir souligné cela):

import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;

@Component
public class StartupHousekeeper {

  @EventListener(ContextRefreshedEvent.class)
  public void contextRefreshedEvent() {
    // do whatever you need here 
  }
}
90
répondu Stefan Haberl 2017-05-23 12:18:02

au printemps 4.2+ vous pouvez maintenant simplement faire:

@Component
class StartupHousekeeper {

    @EventListener(ContextRefreshedEvent.class)
    void contextRefreshedEvent() {
        //do whatever
    }
}
29
répondu bphilipnyc 2016-11-04 03:34:38

pour les utilisateurs de Java 1.8 qui reçoivent un avertissement en essayant de faire référence à l'annotation @PostConstruct, j'ai fini par désactiver l'annotation @Scheduled ce que vous pouvez faire si vous avez déjà un travail @Scheduled avec fixedRate ou fixedDelay.

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@EnableScheduling
@Component
public class ScheduledTasks {

private static final Logger LOGGER = LoggerFactory.getLogger(ScheduledTasks.class);

private static boolean needToRunStartupMethod = true;

    @Scheduled(fixedRate = 3600000)
    public void keepAlive() {
        //log "alive" every hour for sanity checks
        LOGGER.debug("alive");
        if (needToRunStartupMethod) {
            runOnceOnlyOnStartup();
            needToRunStartupMethod = false;
        }
    }

    public void runOnceOnlyOnStartup() {
        LOGGER.debug("running startup job");
    }

}
9
répondu encrest 2015-07-08 22:13:48

Si vous utilisez printemps-boot, c'est la meilleure réponse.

je pense que @PostConstruct et d'autres diverses interjections du cycle de vie sont des voies rondes. Ceux-ci peuvent conduire directement à des problèmes d'exécution ou causer moins que des défauts évidents dus à des événements imprévus du cycle de vie de la fève/contexte. Pourquoi ne pas simplement invoquer directement votre haricot en utilisant le Java ordinaire? Vous invoquez toujours le haricot la "voie du printemps" (par exemple: par l'intermédiaire du proxy AOP du printemps). Et le meilleur de tout, c'est java, Je ne peux pas en avoir plus simple que ça. Pas besoin d'écouteurs de contexte ou d'ordonnanceurs bizarres.

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext app = SpringApplication.run(DemoApplication.class, args);

        MyBean myBean = (MyBean)app.getBean("myBean");

        myBean.invokeMyEntryPoint();
    }
}
9
répondu Zombies 2015-07-22 05:38:10

ce que nous avons fait était d'étendre org.springframework.web.context.ContextLoaderListener pour imprimer quelque chose quand le contexte commence.

public class ContextLoaderListener extends org.springframework.web.context.ContextLoaderListener
{
    private static final Logger logger = LoggerFactory.getLogger( ContextLoaderListener.class );

    public ContextLoaderListener()
    {
        logger.info( "Starting application..." );
    }
}

configurer la sous-classe puis dans web.xml :

<listener>
    <listener-class>
        com.mycomp.myapp.web.context.ContextLoaderListener
    </listener-class>
</listener>
7
répondu Wim Deblauwe 2013-06-11 07:09:41

Attention, ceci est seulement conseillé si votre méthode runOnceOnStartup dépend d'un entièrement initialisé printemps contexte. Par exemple: vous voulez appeler un dao avec démarcation des transactions

vous pouvez également utiliser une méthode planifiée avec fixedDelay mis très élevé

@Scheduled(fixedDelay = Long.MAX_VALUE)
public void runOnceOnStartup() {
    dosomething();
}

Ceci a l'avantage que l'ensemble de l'application est câblé (Transactions, Dao, ...)

vu dans Programmer des tâches à exécuter une fois, en utilisant le namespace des tâches de ressort

3
répondu Joram 2017-05-23 12:26:07

posté une autre solution qui met en œuvre WebApplicationInitializer et est appelé beaucoup avant que n'importe quel grain de printemps est instancié, dans le cas où quelqu'un a ce cas d'utilisation

initialiser la Locale par défaut et le fuseau horaire avec la configuration du ressort

1
répondu kisna 2017-05-23 12:18:02

si vous voulez configurer un bean avant que votre application ne tourne complètement, vous pouvez utiliser @Autowired :

@Autowired
private void configureBean(MyBean: bean) {
    bean.setConfiguration(myConfiguration);
}
0
répondu Cory Klein 2015-11-12 22:34:56
AppStartListener implements ApplicationListener {
    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        if(event instanceof ApplicationReadyEvent){
            System.out.print("ciao");

        }
    }
}
0
répondu dnocode 2016-04-03 12:48:03

vous pouvez utiliser @EventListener sur votre component, qui sera invoqué après le démarrage du serveur et toutes les fèves initialisées.

@EventListener
public void onApplicationEvent(ContextClosedEvent event) {

}
0
répondu krmanish007 2018-05-29 11:49:05