title: 【転載】SpringBoot の初期化時に何かをするための 6 つの方法
date: 2021-08-24 15:19:00
comment: false
toc: true
category:
- Java
tags: - 転載
- Java
- SpringBoot
- 初期化
- 方法
- 方法
- コンテナ
- リフレッシュ
- リスナー
- 起動
- プロジェクト
- イベント
この記事はSpringBoot の初期化時に何かをするための 6 つの方法から転載されています。
前書き#
実際の作業では、プロジェクトの起動時にスレッドプールの初期化や暗号証明書の事前読み込みなど、いくつかの初期化操作を行う必要があります。
そこで、クラシックな質問が出てきます。これは面接官がよく尋ねる質問でもあります:Spring Boot プロジェクトの起動時に何かをする手段は何ですか?
方法はいくつかありますが、以下に一般的な方法をいくつか紹介します。
1、コンテナリフレッシュ完了の拡張ポイント ApplicationListener<ContextRefreshedEvent>
#
ApplicationContext のイベントメカニズムは、オブザーバーデザインパターンを実装しており、ApplicationEvent と ApplicationListener の 2 つのインターフェースを通じて ApplicationContext のイベントメカニズムを実現しています。
Spring にはいくつかの組み込みイベントがあります:
ContextRefreshedEvent
:ApplicationContext が初期化またはリフレッシュされたときに、このイベントが発行されます。これは ConfigurableApplicationContext インターフェースの refresh () メソッドを使用しても発生します。ここでの初期化は、すべての Bean が正常にロードされ、後処理 Bean が検出されてアクティブ化され、すべての Singleton Bean が事前インスタンス化され、ApplicationContext コンテナが準備完了であることを指します。ContextStartedEvent
:ConfigurableApplicationContext(ApplicationContext のサブインターフェース)インターフェースの start () メソッドを使用して ApplicationContext を起動するときに、このイベントが発行されます。データベースを調査したり、このイベントを受け取った後に停止したアプリケーションを再起動したりできます。ContextStoppedEvent
:ConfigurableApplicationContext インターフェースの stop () を使用して ApplicationContext を停止するときに、このイベントが発行されます。このイベントを受け取った後に必要なクリーンアップ作業を行うことができます。ContextClosedEvent
:ConfigurableApplicationContext インターフェースの close () メソッドを使用して ApplicationContext を閉じるときに、このイベントが発行されます。閉じられたコンテキストはライフサイクルの終わりに達し、リフレッシュまたは再起動することはできません。RequestHandledEvent
:これは Web 特有のイベントで、すべての Bean に HTTP リクエストがサービスされたことを通知します。DispatcherServlet を使用する Web アプリケーションにのみ適用されます。Spring をフロントエンドの MVC コントローラーとして使用している場合、Spring がユーザーリクエストを処理した後に自動的にこのイベントがトリガーされます。
さて、上記の組み込みイベントを理解した後、Spring Boot の起動時にContextRefreshedEvent
をリスンしていくつかの操作を行うことができます。コードは以下の通りです:
@Component
public class TestApplicationListener implements ApplicationListener<ContextRefreshedEvent>{
@Override
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
System.out.println(contextRefreshedEvent);
System.out.println("TestApplicationListener............................");
}
}
高度な使い方#
特定のニーズを満たすためにカスタムイベントを作成することもできます。例えば、メール送信が成功した後にビジネス処理を行うことができます。
-
カスタム EmailEvent、コードは以下の通り:
public class EmailEvent extends ApplicationEvent{ private String address; private String text; public EmailEvent(Object source, String address, String text){ super(source); this.address = address; this.text = text; } public EmailEvent(Object source) { super(source); } //......addressとtextのsetter、getter }
-
カスタムリスナー、コードは以下の通り:
public class EmailNotifier implements ApplicationListener{ public void onApplicationEvent(ApplicationEvent event) { if (event instanceof EmailEvent) { EmailEvent emailEvent = (EmailEvent)event; System.out.println("メールアドレス:" + emailEvent.getAddress()); System.out.println("メール内容:" + emailEvent.getText()); } else { System.out.println("コンテナ自体のイベント:" + event); } } }
-
メール送信後、イベントをトリガーするコードは以下の通り:
public class SpringTest { public static void main(String args[]){ ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml"); //ApplicationEventオブジェクトを作成 EmailEvent event = new EmailEvent("hello","[email protected]","これはテストです"); //このイベントを明示的にトリガー context.publishEvent(event); } }
2、SpringBoot
のCommandLineRunner
インターフェース#
コンテナの初期化が完了した後、CommandLineRunner
のrun()
メソッドが呼び出され、コンテナ起動後に何かを行うことができます。この方法は ApplicationListener と比較してより柔軟です。以下のように:
- 異なる
CommandLineRunner
の実装は、@Order()
を使用して実行順序を指定できます。 - コンソールから入力されたパラメータを受け取ることができます。
以下にカスタム実装クラスを示します。コードは以下の通り:
@Component
@Slf4j
public class CustomCommandLineRunner implements CommandLineRunner {
/**
* @param args コンソールから渡されたパラメータを受け取る
*/
@Override
public void run(String... args) throws Exception {
log.debug("コンソールから受け取ったパラメータ>>>>"+ Arrays.asList(args));
}
}
この jar を実行するコマンドは以下の通り:
java -jar demo.jar aaa bbb ccc
上記のコマンドでは、3 つのパラメータaaa
、bbb
、ccc
が渡され、これらのパラメータはrun()
メソッドで受け取られます。以下の図のように:
ソースコード分析#
私の文章を読んだファンは、CommandLineRunner
がどのように実行されるかを知っているはずです。元の文:頭が薄くなるシリーズ、23 枚の図で Spring Boot の起動プロセスをソースコードから分析する~
Spring Boot がコンテキストをロードするエントリはorg.springframework.context.ConfigurableApplicationContext()
メソッドにあります。以下の図のように:
CommandLineRunner を呼び出すのはcallRunners(context, applicationArguments);
というメソッドで実行されます。ソースコードは以下の図のように:
3、SpringBoot
のApplicationRunner
インターフェース#
ApplicationRunner
とCommandLineRunner
はどちらも Spring Boot が提供するもので、CommandLineRunner
に比べてコンソールから渡されたパラメータのラッピングがより良好です。例えば、--version=2.1.0
のようにキーと値のペアで指定されたパラメータを取得できます。
この時、jar を実行するコマンドは以下の通り:
java -jar demo.jar --version=2.1.0 aaa bbb ccc
上記のコマンドでは、4 つのパラメータが渡されます。1 つのキーと値のペアversion=2.1.0
と、他の 3 つはそれぞれaaa
、bbb
、ccc
です。
同様に、@Order()
を使用して優先順位を指定できます。以下のコードのように:
@Component
@Slf4j
public class CustomApplicationRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
log.debug("コンソールから受け取ったパラメータ:{},{},{}",args.getOptionNames(),args.getNonOptionArgs(),args.getSourceArgs());
}
}
上記のコマンドを実行すると、結果は以下の図のようになります:
ソースコード分析#
CommandLineRunner
と同様に、callRunners()
メソッド内で実行されます。ソースコードは以下の図のように:
4、@PostConstruct
アノテーション#
最初の 3 つはコンテナの初期化が完了した後に行う操作に対して、@PostConstruct
アノテーションは Bean の初期化が完了した後に行う操作に対して使用されます。例えば、リスナーを登録するなどです。
@PostConstruct
アノテーションは一般に Bean のメソッドに置かれ、Bean の初期化が完了した後にこのメソッドが呼び出されます。コードは以下の通り:
@Component
@Slf4j
public class SimpleExampleBean {
@PostConstruct
public void init(){
log.debug("Beanの初期化が完了し、呼び出し...........");
}
}
5、@Bean アノテーションで初期化メソッドを指定#
この方法は@PostConstruct
と似ており、Bean の初期化が完了した後に呼び出されるメソッドを指定します。
新しい Bean を作成するコードは以下の通り:
@Slf4j
public class SimpleExampleBean {
public void init(){
log.debug("Beanの初期化が完了し、呼び出し...........");
}
}
設定クラスで@Bean
を使用してこの Bean をインスタンス化しますが、@Bean
のinitMethod
属性で初期化後に実行するメソッドを指定する必要があります。以下のように:
@Bean(initMethod = "init")
public SimpleExampleBean simpleExampleBean(){
return new SimpleExampleBean();
}
6、 InitializingBean
インターフェース#
InitializingBean
の使い方は基本的に@PostConstruct
と同じですが、対応する Bean はafterPropertiesSet
メソッドを実装する必要があります。コードは以下の通り:
@Slf4j
@Component
public class SimpleExampleBean implements InitializingBean {
@Override
public void afterPropertiesSet() {
log.debug("Beanの初期化が完了し、呼び出し...........");
}
}
まとめ#
実装方法はいくつかあり、著者は一般的な 6 つの方法をまとめただけです。学んだ方はいいねを押してください。