SpringBoot初期化のいくつかの大きな技を見てやっと分かった.


背景
通常の開発では、SpringBootアプリケーションの起動時に次のような論理を実行する必要があります.
  • 現在の環境のいくつかの構成または変数
  • を取得する
  • データベースへの初期データの書き込み
  • 特定のサードパーティシステムに接続し、相手が動作できることを確認します.

  • これらの機能を実装すると、いくつかの「穴」に遭遇する可能性があります.SpringBootフレームワークの利便性を利用するために,アプリケーション全体の実行制御権をコンテナに渡さざるを得ず,詳細については何も知られていない.では、初期化ロジックコードを実装する際に注意する必要があります.たとえば、次のコードのように、Beanクラスの構築方法で初期化ロジックを実装することは簡単ではありません.
    @Component
    public  class  InvalidInitExampleBean {
    
         @Autowired
         private  Environment env;
    
         public  InvalidInitExampleBean() {
              env.getActiveProfiles();
         }
    }

    ここでは、InvalidInitExampleBeanの構築方法で、自動注入envフィールドにアクセスしようとしています.実際に実行すると、空のポインタ異常(Null PointerException)が得られます.
    なぜなら、SpringコンテキストのEnvironmentというBeanは、コンストラクションメソッドが呼び出されると、まだインスタンス化されておらず、現在のオブジェクトにも注入されていない可能性が高いため、呼び出すことができないからです.
    次に、SpringBootでセキュリティ初期化を実現する方法を見てみましょう.
    1、@PostConstruct注記
    @PostConstruct注記は、実際にはjavaxの拡張パッケージ(Springフレームワークからのイメージが多い)から来ており、Beanオブジェクトの初期化が完了した後に実行される方法を宣言する役割を果たしています.
    元の定義を見てみましょう.
    The PostConstruct annotation is used on a method that needs to be executed  after dependency injection is done to perform any initialization
    すなわち,この方法はすべての依存フィールドが注入された後に実行されるが,もちろんSpringフレームワークによって実行される.
    @PostConstructを使用した例を以下のコードで示します.
    2、InitializingBeanインタフェース
    InitializingBeanはSpringフレームワークによって提供されるインタフェースであり,@PostConstruct注釈の動作原理と非常に類似している.注記を使用しない場合は、BeanインスタンスにInitializingBeanインタフェースを継承させ、afterPropertiesSet()という方法を実装する必要があります.
    次のコードは、この使い方を示しています.
    3、@Bean initMethodメソッド
    Beanを宣言するときに、初期化後に実行されることを示すinitMethodプロパティを同時に指定できます.
    次のようになります.
    次に、ここではinitMethodをinitメソッドに向け、Beanでこのメソッドを実装する必要があります.
    上のコードはJava注記に基づいており、Xml構成を使用しても同様の効果が得られます.
    この方式は以前のSpringバージョンで多く使われていた.
    4、コンストラクタ注入
    依存するフィールドがBeanの構築方法で宣言されている場合、Springフレームワークは、これらのフィールドに対応するBeanをインスタンス化してから、現在の構築方法を呼び出します.この場合、構造方法のいくつかの操作も安全です.以下のようにします.
    5、 ApplicationListener
    ApplicationListenerはspring-contextコンポーネントによって提供されるインタフェースで、主に「コンテナコンテキストのライフサイクルイベント」を傍受するために使用されます.定義は次のとおりです.
    ここでeventは、ApplicationEventに継承されたイベントオブジェクトであってもよい.初期化作業では、ContextRefreshedEventというイベントをリスニングすることで、コンテキスト初期化のタイミングをキャプチャできます.次のコードに従います.
    Springコンテキストの初期化が完了すると、ここで定義した方法が実行されます.前のInitializingBeanとは異なり、ApplicationListenerによる傍受はグローバルであり、つまりすべてのBeanが初期化されてから実行される.
    Spring 4.2以降に新たな@EventListener注記が導入され,同様の効果が得られる.
    6、 CommandLineRunner
    SpringBootは、アプリケーション起動後の論理制御を実現するCommanLineRunnerインタフェースを提供し、以下のように定義されています.
    ここでrunメソッドはSpringコンテキストの初期化が完了すると実行され、アプリケーションの起動パラメータが入力されます.次のコードに従います.
    また、@Order注記は、複数のCommandLineRunnerの場合に使用して順序を制御できます.
    7、 ApplicationRunner
    CommandLineRunnerインタフェースと同様に、Spring bootはまた、初期化ロジックを実装するための別のApplicationRunnerインタフェースを提供します.違うところはApplicationRunnerですrun()メソッドは、単純な文字列パラメータではなく、カプセル化されたApplicationArgumentsパラメータオブジェクトを受け入れます.
    ApplicationArgumentsオブジェクトは、解析後のパラメータを直接取得するための便利な方法を提供します.たとえば、次のようにします.
    java -jar application.jar --debug --ip=xxxx

    このときApplicationArgumentsのgetOptionNamesで[debug]、[ip]という値が得られます.
    テストコード
    以下では,いくつかの初期化方法の実行順序を小さなテストにより実証する.
    複合Beanを次のコードで実装します.
    このBeanの初期化を実行すると、ログ出力は次のようになります.
    したがって、これらの初期化の順序は次のとおりです.
  • コンストラクタ方法
  • @PostConstruct注記方法
  • InitializingBeanのafterPropertiesSet()
  • Bean定義initMethodプロパティメソッド