Spring Bootの開始後にコードを実行する


211

Spring -Bootアプリがディレクトリの変更を監視し始めた後にコードを実行したいと思います。

新しいスレッドを実行してみましたが、@Autowiredその時点ではサービスが設定されていません。

アノテーションが設定さApplicationPreparedEventれる前に発生するを見つけることができました@Autowired。理想的には、アプリケーションがhttpリクエストを処理する準備ができたらイベントを発生させたいと思います。

使用するより良いイベント、またはアプリケーションがスプリングブートでライブになった後にコードを実行するより良い方法はありますか?



Springブートは、ApplicationRunnerとCommandLineRunnerの2つのインターフェイスを提供します。これらは、Springブートの開始後にコードを実行するときに使用できます。実装例については、この記事を参照してください-jhooq.com/applicationrunner-spring-boot
Rahul

回答:


121

試してください:

@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
アプリケーションをwarファイルとして外部tomcatにデプロイする場合、これは機能しません。埋め込まれたTomcatでのみ機能します
Saurabh 2016年

いいえ、機能しません。ただし、この使用例では、の代わりに、より明示的な方法が好きです@Component。warファイルで機能させるには、@ cjstehnoからの回答を参照してください。
アントンベソノフ2016年

320

それはこれと同じくらい簡単です:

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

バージョンでテスト済み 1.5.1.RELEASE


7
ありがとうございます。これにより、コードを変更せずに機能させることができました。そのような簡単な答えをありがとう。これは、@ RequestMappingアノテーションでも問題なく機能します。
ハーシット2017

16
誰かが@EventListener(ContextRefreshedEvent.class)代わりに使用したいかもしれません。これは、Beanの作成後、サーバーが起動する前にトリガーされます。リクエストがサーバーに到達する前にアクティビティを実行するために使用できます。
neeraj 2018年

3
@neeraj、問題はSpring Bootが起動した後にコードを実行することです。を使用するとContextRefreshedEvent、更新のたびにも実行されます。
cahen

4
Spring boot 2.0.5.RELEASEでテスト済み
ritesh

2
2.2.2リリースでテスト済み。それは完全に動作します。このソリューションは私の時間を節約します。
アーフィル

96

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

コード:http : //blog.netgloo.com/2014/11/13/run-code-at-spring-boot-startup/

これは、ドキュメントがスタートアップイベントについて言及しているものです。

...

アプリケーションイベントは、アプリケーションの実行時に次の順序で送信されます。

ApplicationStartedEventは、実行の開始時に送信されますが、リスナーと初期化子の登録を除くすべての処理の前に送信されます。

ApplicationEnvironmentPreparedEventは、コンテキストで使用される環境がわかっている場合に、コンテキストが作成される前に送信されます。

ApplicationPreparedEventは、更新が開始される直前、ただしBean定義がロードされた後に送信されます。

アプリケーションがリクエストを処理する準備ができていることを示すために、更新および関連するコールバックが処理された後、ApplicationReadyEventが送信されます。

起動時に例外が発生した場合、ApplicationFailedEventが送信されます。

...


11
別の@EventListener方法として、Beanメソッドのアノテーションを使用してこれを行い、フックするクラスイベントを引数として渡すことができます。
padilo

2
これが選ばれた答えであるべきです。
varun113 2017

2
これは、spring-boot 2で変更されました。1.xから移植し、ApplicationStartedEventを使用していた場合は、代わりにApplicationStartingEventが必要になります。
アンディブラウン

これは完全に問題なく機能し、私は最善の方法を考えています。
AVINASH SHRIMALI 2018

あなたは最高です
ancm

83

次のような初期化時にモニターを起動するBeanを作成しないのはなぜですか。

@Component
public class Monitor {
    @Autowired private SomeService service

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

このinitメソッドは、Beanの自動配線が完了するまで呼び出されません。


14
時々@PostConstruct早すぎる発射。たとえば、Spring Cloud Stream Kafkaを使用する場合、@PostConstructアプリケーションがKafkaにバインドする前に発生します。Dave Syerのソリューションは、タイミングよく起動するため、優れています。
Elnur Abdurrakhimov 2017

9
@PostConstruct後ではなく、初期化中に発生します。これは場合によっては便利ですが、Spring Bootの起動に実行したい場合は、正しい答えではありません。たとえば、@PostConstruct終了しませんが、使用可能なエンドポイントはありません。
cahen 2017

63

「スプリングブート」の方法は、を使用することCommandLineRunnerです。そのタイプの豆を追加するだけでよいのです。Spring 4.1(Boot 1.2)にはSmartInitializingBean、すべてが初期化された後にコールバックを取得するもあります。そしてSmartLifecycle(春3から)あります。


その例は?アプリの実行後、コマンドラインを介して任意の瞬間にBeanを実行することは可能ですか?
エミリオ

5
「任意の瞬間」とはどういう意味かわからない。Spring Bootユーザーガイドとサンプルには、CommandLineRunner(およびそれ以降のApplicationRunner)を使用した例があります。docs.spring.io / spring-boot / docs / current-SNAPSHOT / reference /
Dave Syer、2015

アプリケーションの開始/停止ステージで非同期タスクを実行するには、Lifecycleが推奨されるオプションであることがわかりました。CommandLineRunnerとInitializingBeansの間の他の違いを見つけようとしましたが、それについては何も見つかりません。
saljuama

3
カップルの通常の使用例のコードCommandLineRunner
Alexey Simonov 2018

41

を使用してクラスを拡張しApplicationRunnerrun()メソッドをオーバーライドして、そこにコードを追加できます。

import org.springframework.boot.ApplicationRunner;

@Component
public class ServerInitializer implements ApplicationRunner {

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

        //code goes here

    }
}

春のブーツに最適です。しかし、クラスにApplicationScopeがある場合、run()メソッドが2回呼び出されました。したがって、上記のPostConstructメソッドの方がうまくいきました。
サム

26

ApplicationReadyEvent実際に役立つのは、実行したいタスクがサーバーを正しく操作するための要件ではない場合だけです。変更を監視するために非同期タスクを開始するのが良い例です。

ただし、タスクが完了するまでサーバーが「準備ができていない」状態のSmartInitializingSingleton場合は、RESTポートが開かれ、サーバーがビジネスのために開かれるにコールバックを取得するため、実装することをお勧めします。

@PostConstruct一度だけ発生するはずのタスクに使用したくありません。複数回呼び出されていることに気付くと失礼な驚きを覚えます...


これが選ばれた答えであるべきです。@Andyが指摘するように、SmartInitializingSingletonは、ポートが開かれる直前に呼び出されます。
Srikanth

24

スプリング構成の場合:

@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春に豆を使用> 4.1

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

}

別の方法として、CommandLineRunnerBeanを実装するか、Beanメソッドにでアノテーションを付けることができます@PostConstruct


そのメソッド内にAutowired依存関係を要求できますか?プロファイルを設定したい
LppEdd

7

魅力のように機能したDave Syerの回答の例を示します。

@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

これを試してみてください。アプリケーションコンテキストが完全に開始すると、コードが実行されます。

 @Component
public class OnStartServer implements ApplicationListener<ContextRefreshedEvent> {

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

6

EventListener@cahenによる注釈の使用に関する提案(https://stackoverflow.com/a/44923402/9122660)は非常にクリーンであるため、私は本当に気に入っています。残念ながら、Spring + Kotlinの設定でこれを機能させることはできませんでした。Kotlinで機能するのは、クラスをメソッドパラメータとして追加することです。

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

ランダムに外に出さずに、スプリングブートアプリケーションクラスに配置します@SpringBootApplication class MyApplication { @EventListener(ApplicationReadyEvent::class) fun doSomethingAfterStartup() { println("hello world, I have just started up") } }
アーメドナ

@SpringBootApplicationクラスに必要とする必要はありません。すべての構成クラスで実行
ジョージマリン

5

Spring Bootアプリケーションの起動後にコードブロックを実行する最良の方法は、PostConstructアノテーションを使用することです。または、同じためにコマンドラインランナーを使用することもできます。

1. PostConstructアノテーションの使用

@Configuration
public class InitialDataConfiguration {

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

}

2.コマンドラインランナーBeanを使用する

@Configuration
public class InitialDataConfiguration {

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

3

スプリングブートアプリケーションにCommandLineRunnerを実装するだけです。runメソッドを実装する必要があります。

public classs SpringBootApplication implements CommandLineRunner{

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

        }
}

0

CommandLineRunnerまたはApplicationRunnerを使用する最良の方法run()メソッドの唯一の違いは、CommandLineRunnerが文字列の配列を受け入れ、ApplicationRunnerがApplicationArugumentを受け入れることです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.