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.
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 rappelInitializingBean
- 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.
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
}
}
au printemps 4.2+ vous pouvez maintenant simplement faire:
@Component
class StartupHousekeeper {
@EventListener(ContextRefreshedEvent.class)
void contextRefreshedEvent() {
//do whatever
}
}
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");
}
}
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();
}
}
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>
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
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
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);
}
AppStartListener implements ApplicationListener {
@Override
public void onApplicationEvent(ApplicationEvent event) {
if(event instanceof ApplicationReadyEvent){
System.out.print("ciao");
}
}
}
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) {
}