it-swarm.com.de

Methode beim Start in Spring ausführen

Gibt es eine Spring 3-Funktion zum Ausführen einiger Methoden, wenn die Anwendung zum ersten Mal gestartet wird? Ich weiß, dass ich den Trick des Einrichtens einer Methode mit @Scheduled annotation ausführen kann. Diese Methode wird direkt nach dem Start ausgeführt, aber dann wird sie regelmäßig ausgeführt.

157
Javi

Wenn Sie mit "Anwendungsstart" "Anwendungskontextstart" meinen, dann gibt es ja viele Möglichkeiten, dies zu tun . Die einfachste Methode (für Singletons-Beans jedenfalls) besteht darin, Ihre Methode mit @PostConstruct zu kommentieren. Schauen Sie sich den Link an, um die anderen Optionen zu sehen, aber zusammenfassend sind dies:

  • Mit @PostConstruct kommentierte Methoden
  • afterPropertiesSet(), wie von der Callback-Schnittstelle InitializingBean definiert
  • Eine benutzerdefiniert konfigurierte Methode init ()

Technisch gesehen handelt es sich dabei nicht nur um den Kontextlebenszyklus, sondern um einen Einstieg in den bean - Lebenszyklus, in 99% der Fälle sind die beiden jedoch gleichwertig.

Wenn Sie sich speziell in den Kontext Start/Herunterfahren einbinden müssen, können Sie stattdessen die Lifecycle-Schnittstelle implementieren , dies ist jedoch wahrscheinlich nicht erforderlich.

172
skaffman

Dies ist leicht mit einer ApplicationListener möglich. Ich habe es verstanden, Spring's ContextRefreshedEvent zuzuhören:

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 
  }
}

Anwendungs-Listener werden im Frühling synchron ausgeführt. Wenn Sie sicherstellen möchten, dass der Code nur einmal ausgeführt wird, behalten Sie einfach einen Status in Ihrer Komponente bei.

UPDATE

Ab Spring 4.2+ können Sie auch die @EventListener-Anmerkung verwenden, um die ContextRefreshedEvent zu beobachten (danke an @bphilipnyc für diesen Hinweis):

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 
  }
}
94
Stefan Haberl

Im Frühjahr 4.2+ können Sie jetzt einfach Folgendes tun:

@Component
class StartupHousekeeper {

    @EventListener(ContextRefreshedEvent.class)
    void contextRefreshedEvent() {
        //do whatever
    }
}
32
bphilipnyc

Für Java 1.8-Benutzer, die beim Versuch, auf die @PostConstruct-Annotation zu verweisen, eine Warnung erhalten, landete ich stattdessen mit der @Scheduled-Annotation. Dies ist möglich, wenn Sie bereits einen @Scheduled-Job mit fixedRate oder fixedDelay haben.

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
encrest

Wenn Sie Spring-Boot verwenden, ist dies die beste Antwort.

Ich fühle, dass @PostConstruct und andere verschiedene Lebenszyklus-Interjektionen rundherum sind. Diese können direkt zu Laufzeitproblemen führen oder aufgrund unerwarteter Bean-Lifecycle-Ereignisse weniger offensichtliche Fehler verursachen. Warum rufen Sie Ihre Bean nicht einfach direkt mit Java auf? Sie rufen die Bohne immer noch "spring way" an (z. B. durch den Spring AoP Proxy). Und das Beste ist, es ist reines Java, einfacher geht es nicht. Es sind keine Kontextlistener oder ungeraden Scheduler erforderlich.

@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
Zombies

Wir haben org.springframework.web.context.ContextLoaderListener erweitert, um etwas zu drucken, wenn der Kontext beginnt.

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

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

Konfigurieren Sie die Unterklasse dann in web.xml:

<listener>
    <listener-class>
        com.mycomp.myapp.web.context.ContextLoaderListener
    </listener-class>
</listener>
7
Wim Deblauwe

Achtung, dies wird nur empfohlen, wenn Ihre runOnceOnStartup-Methode von einer .__ abhängt. vollständig initialisierter Frühlingskontext. Zum Beispiel: Sie möchten ein Dao anrufen mit Transaktionsabgrenzung

Sie können eine geplante Methode auch verwenden, wenn fixedDelay sehr hoch eingestellt ist

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

Dies hat den Vorteil, dass die gesamte Anwendung verkabelt ist (Transactions, Dao, ...).

gesehen in Planen von Tasks zur einmaligen Ausführung mit dem Spring-Task-Namespace

3
Joram

Mit SpringBoot können wir beim Start eine Methode über @EventListener annotation ausführen

@Component
public class LoadDataOnStartUp
{   
    @EventListener(ApplicationReadyEvent.class)
    public void loadData()
    {
        // do something
    }
}

Eine andere Lösung wurde veröffentlicht, die WebApplicationInitializer implementiert und lange vor dem Instanziieren eines Spring-Beans aufgerufen wird, falls jemand diesen Anwendungsfall hat

Standard-Gebietsschema und Zeitzone mit Spring-Konfiguration initialisieren

1
kisna

Wenn Sie eine Bean konfigurieren möchten, bevor Ihre Anwendung vollständig ausgeführt wird, können Sie @Autowired verwenden:

@Autowired
private void configureBean(MyBean: bean) {
    bean.setConfiguration(myConfiguration);
}
0
Cory Klein
AppStartListener implements ApplicationListener {
    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        if(event instanceof ApplicationReadyEvent){
            System.out.print("ciao");

        }
    }
}
0
dnocode

Für eine Datei StartupHousekeeper.Java, die sich im Paket com.app.startup befindet,

Tun Sie dies in StartupHousekeeper.Java:

@Component
public class StartupHousekeeper {

  @EventListener(ContextRefreshedEvent.class)
  public void keepHouse() {
    System.out.println("This prints at startup.");
  }
}

Und dies in myDispatcher-servlet.Java:

<?xml version="1.0" encoding="UTF-8"?>
<beans>

    <mvc:annotation-driven />
    <context:component-scan base-package="com.app.startup" />

</beans>
0
Cameron Hudson

Sie können @EventListener für Ihre Komponente verwenden, die nach dem Start des Servers und der Initialisierung aller Beans aufgerufen wird.

@EventListener
public void onApplicationEvent(ContextClosedEvent event) {

}
0
krmanish007