Spring Boot başladıktan sonra çalışan kod


211

Bahar önyükleme uygulamamın bir dizini değişiklikler için izlemeye başladıktan sonra kodu çalıştırmak istiyorum .

Yeni bir iş parçacığı çalıştırmayı denedim ama @Autowiredhizmetleri bu noktada ayarlanmamış.

Ek açıklamalar ApplicationPreparedEventkoyulmadan önce hangi ateşi bulabileceğimi buldum @Autowired. İdeal olarak uygulama http isteklerini işlemek için hazır olduğunda olay ateş etmek istiyorum.

Kullanılacak daha iyi bir olay var mı veya uygulama bahar önyüklemesinde yayınlandıktan sonra kod çalıştırmanın daha iyi bir yolu var mı?



Yay önyüklemesi, bahar önyüklemesi başladıktan sonra kodu çalıştırmak istediğinizde kullanılabilecek iki ApplicationRunner ve CommandLineRunner arabirimi sağlar. Uygulama örneği için bu makaleye başvurabilirsiniz - jhooq.com/applicationrunner-spring-boot
Rahul

Yanıtlar:


121

Deneyin:

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

6
uygulamayı harici bir tomcat'e savaş dosyası olarak dağıttığınızda bu çalışmaz. Sadece gömülü tomcat ile çalışır
Saurabh

Hayır, çalışmıyor. Ancak bu kullanım durumunda, yerine daha açık bir şekilde seviyorum @Component. Savaş dosyasında çalışmasını sağlamak için @cjstehno'nun yanıtına bakın.
Anton Bessonov

320

Bu kadar basit:

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

Sürümde test edildi 1.5.1.RELEASE


7
teşekkürler. Bu benim kod herhangi bir değişiklik gerekmeden çalışması yaptı. Böyle basit bir cevap için tekrar teşekkürler. Bu ayrıca @RequestMapping ek açıklamasıyla sorunsuz çalışacaktır.
Harshit

16
Birisi @EventListener(ContextRefreshedEvent.class)bunun yerine kullanmak isteyebilir , bu da fasulye oluşturulduktan sonra, ancak sunucu başlamadan önce tetiklenir. Herhangi bir istek sunucuya ulaşmadan önce etkinlikler gerçekleştirmek için kullanılabilir.
neeraj

3
@neeraj, soru Spring Boot başladıktan sonra kod çalıştırmak hakkındadır. Kullanırsanız ContextRefreshedEvent, her yenileme sonrasında da çalışır.
cahen

4
İlkbahar botu 2.0.5 üzerinde test edildi.RELEASE
ritesh

2
2.2.2 Sürümünde test edilmiştir. mükemmel çalışıyor. bu çözüm zaman kazandırır.
Arphile

96

ApplicationReadyEvent'i denediniz mi?

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

Kod kaynağı: http://blog.netgloo.com/2014/11/13/run-code-at-spring-boot-startup/

Belgelerin başlangıç ​​olayları hakkında söylediği şey :

...

Uygulamanız çalıştıkça, uygulama olayları aşağıdaki sırayla gönderilir:

Bir uygulamanın başlangıcında, ancak dinleyicilerin ve başlatıcıların kaydı dışındaki herhangi bir işlemden önce bir ApplicationStartedEvent gönderilir.

Bağlamda kullanılacak Ortam biliniyor, ancak bağlam oluşturulmadan önce bir ApplicationEnvironmentPreparedEvent gönderilir.

Bir ApplicationPreparedEvent, yenileme başlamadan hemen önce, ancak fasulye tanımları yüklendikten sonra gönderilir.

Yenilemeden sonra bir ApplicationReadyEvent gönderilir ve ilgili hizmet geri bildirimleri, uygulamanın hizmet isteklerine hazır olduğunu belirtmek için işlenir.

Başlangıçta bir istisna varsa bir ApplicationFailedEvent gönderilir.

...


11
Alternatif olarak, @EventListenerbağlamak istediğiniz sınıf olayını argüman olarak ileterek, Bean yöntemindeki ek açıklamayı kullanarak bunu yapabilirsiniz .
padilo

2
Seçilen cevap bu olmalıdır.
varun113

2
Bu, ilkbahar önyükleme 2'de değişti. 1.x'den yukarı taşıyorsanız ve ApplicationStartedEvent kullanıyorsanız, şimdi bunun yerine ApplicationStartingEvent'i istiyorsunuz.
Andy Brown

Bu kesinlikle iyi çalışıyor ve bence en iyi yol.
AVINASH SHRIMALI

sen en
iyisin

83

Neden sadece başlangıçta monitörünüzü başlatan bir fasulye oluşturmuyorsunuz?

@Component
public class Monitor {
    @Autowired private SomeService service

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

initHerhangi Autowiring fasulye için yapılana kadar yöntemi denir edilmeyecektir.


14
Bazen @PostConstructçok erken patlar. Örneğin, Spring Cloud Stream Kafka kullanırken, @PostConstructuygulama Kafka'ya bağlanmadan önce ateşlenir. Dave Syer'in çözümü daha iyi çünkü zamanında işliyor.
Elnur Abdurrakhimov

9
@PostConstructbaşlatma sırasında olur, sonra değil. Bu bazı durumlarda yararlı olabilir, ancak Spring Boot başladıktan sonra çalıştırmak istiyorsanız doğru cevap değildir . Örneğin, @PostConstructbitmezken, uç noktaların hiçbiri mevcut değildir.
cahen

63

"Spring Boot" yolu a kullanmaktır CommandLineRunner. Sadece bu tür fasulye ekleyin ve gitmeye hazırsınız. Bahar 4.1'de (Önyükleme 1.2), SmartInitializingBeanher şey başlatıldıktan sonra geri çağrı alan bir de vardır. Ve SmartLifecycle(İlkbahar 3'ten) var.


Bunun bir örneği var mı? Uygulama çalıştırıldıktan sonra, keyfi bir anda komut satırı üzerinden bir fasulye çalıştırmak mümkün müdür?
Emilio

5
"Keyfi an" ile ne demek istediğini bilmiyorum. Spring Boot kullanıcı kılavuzunda ve örneklerinde a CommandLineRunner(ve daha yenisi ApplicationRunner) kullanım örnekleri vardır : docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/… .
Dave Syer

Yaşam Döngüsü, uygulamanın başlatma / durdurma aşamalarında eşzamansız görevleri gerçekleştirmek için tercih edilen seçenek olduğunu buldum ve CommandLineRunner ve InitializingBeans arasındaki diğer farklılıkları bulmaya çalışıyorum, ancak bu konuda hiçbir şey bulamıyorum.
saljuama

3
birkaç alışılmış örnek kod kullanmaCommandLineRunner
Alexey Simonov

41

Kullanarak bir sınıfı genişletebilir ApplicationRunner, run()yöntemi geçersiz kılabilir ve kodu oraya ekleyebilirsiniz.

import org.springframework.boot.ApplicationRunner;

@Component
public class ServerInitializer implements ApplicationRunner {

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

        //code goes here

    }
}

Spring Boot'da mükemmel. Ancak, sınıf için ApplicationScope uygulandığında run () yöntemi iki kez çağrıldı. Yani yukarıdaki ile PostConstruct yöntemi daha iyi çalıştı.
Sam

26

ApplicationReadyEventyalnızca gerçekleştirmek istediğiniz görev doğru sunucu işlemi için bir gereksinim değilse yararlıdır. Değişiklikleri izlemek için bir zaman uyumsuz görev başlatmak iyi bir örnektir.

Bununla birlikte, görev tamamlanıncaya kadar sunucunuz 'hazır değil' durumundaysa , REST bağlantı noktası açılmadan ve sunucunuz iş için açık olmadan önceSmartInitializingSingleton geri aramayı alacağınız için uygulanması daha iyidir .

@PostConstructSadece bir kez gerçekleşmesi gereken görevler için kullanmaya cazip olmayın . Birden fazla kez çağrıldığını fark ettiğinizde kaba bir sürpriz alacaksınız ...


Seçilen cevap bu olmalıdır. @Andy'nin işaret ettiği gibi, SmartInitializingSingleton bağlantı noktaları açılmadan hemen önce çağrılır.
Srikanth

24

Yay konfigürasyonu ile:

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

12

SmartInitializingSingletonİlkbaharda fasulye kullanın > 4.1

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

}

Alternatif olarak, bir CommandLineRunnerfasulye ile bir fasulye yöntemi uygulanabilir veya açıklanabilir @PostConstruct.


Bu yöntemin içinde Otomatik Kablolu bağımlılığa gereksinim duyabilir miyim? Profiller
LppEdd

7

Bir cazibe gibi çalışan Dave Syer cevabı için bir örnek sunmak:

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

7

Bunu deneyin ve uygulama içeriği tamamen başladığında kodunuzu çalıştıracaktır.

 @Component
public class OnStartServer implements ApplicationListener<ContextRefreshedEvent> {

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

6

Gerçekten kullanımına yönelik öneriyi beğendi EventListener@cahen (tarafından ek açıklama https://stackoverflow.com/a/44923402/9122660 çok temiz olduğundan). Ne yazık ki bunu bir Bahar + Kotlin kurulumunda çalıştıramadım. Kotlin için işe yarayan şey, yöntemi bir parametre parametresi olarak eklemektir:

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

Bahar çizme uygulama sınıfına rastgele dışarı tarafında değil@SpringBootApplication class MyApplication { @EventListener(ApplicationReadyEvent::class) fun doSomethingAfterStartup() { println("hello world, I have just started up") } }
Ahmed na

@SpringBootApplication sınıfına zorunlu tutmanız gerekmez. herhangi bir yapılandırma sınıfı yapacak
George Marin

5

Spring Boot uygulaması başlatıldıktan sonra kod bloğunu yürütmenin en iyi yolu PostConstruct ek açıklamasını kullanmaktır.Ayrıca aynı komut satırı çalıştırıcısını da kullanabilirsiniz.

1. PostConstruct ek açıklamasını kullanma

@Configuration
public class InitialDataConfiguration {

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

}

2. Komut satırı koşucu fasulye kullanarak

@Configuration
public class InitialDataConfiguration {

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

3

sadece bahar önyükleme uygulaması için CommandLineRunner uygulayın. Run yöntemini uygulamanız gerekiyor,

public classs SpringBootApplication implements CommandLineRunner{

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

        }
}

0

CommandLineRunner veya ApplicationRunner'ı kullanmanın en iyi yolu CommandLineRunner dize dizisini kabul eder ve ApplicationRunner ApplicationArugument'i kabul eder.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.