質問

マネージド Bean では、 @PostConstruct 通常の Java オブジェクト コンストラクターの後に呼び出されます。

なぜ使用するのか @PostConstruct 通常のコンストラクター自体ではなく、Bean によって初期化するにはどうすればよいですか?

役に立ちましたか?

解決

  • なぜなら、コンストラクターが呼び出されたとき、Bean はまだ初期化されていないからです。依存関係は注入されません。の中に @PostConstruct メソッドでは、Bean が完全に初期化され、依存関係を使用できるようになります。

  • これは、このメソッドが Bean のライフサイクルで 1 回だけ呼び出されることを保証する契約であるためです。(可能性は低いですが) Bean が内部動作中にコンテナによって複数回インスタンス化されることが起こりますが、それは保証されます。 @PostConstruct は 1 回だけ呼び出されます。

他のヒント

のメインの問題があることです

  コンストラクタで、依存性の注入がまだ発生していない*

<サブ> *明らか除くコンストラクタ・インジェクション

<時間>

実際の例:

public class Foo {

    @Inject
    Logger LOG;

    @PostConstruct
    public void fooInit(){
        LOG.info("This will be printed; LOG has already been injected");
    }

    public Foo() {
        LOG.info("This will NOT be printed, LOG is still null");
        // NullPointerException will be thrown here
    }
}
<時間>

重要の: @PostConstruct@PreDestroyを完全にジャワ11 の中で削除されましたの。

それらを使用して維持するには、を追加する必要がありますあなたの依存関係にjavax.annotation-API のJARます。

Mavenの

<!-- https://mvnrepository.com/artifact/javax.annotation/javax.annotation-api -->
<dependency>
    <groupId>javax.annotation</groupId>
    <artifactId>javax.annotation-api</artifactId>
    <version>1.3.2</version>
</dependency>

のGradle

// https://mvnrepository.com/artifact/javax.annotation/javax.annotation-api
compile group: 'javax.annotation', name: 'javax.annotation-api', version: '1.3.2'

あなたのクラスを実行する場合は、すべてのコンストラクタで初期化の後、@PostConstructは確かに冗長化されます。

あなたのクラスはその依存関係は、setterメソッドを使用して注射した場合、しかし、その後、クラスのコンストラクタは完全にオブジェクトを初期化することはできませんし、すべてのsetterメソッドが@PostConstructのユースケース、したがって、呼び出された後、時々、いくつかの初期化のニーズは、実行されます。

次のシナリオを考えてみましょう。

public class Car {
  @Inject
  private Engine engine;  

  public Car() {
    engine.initialize();  
  }
  ...
}

Car はフィールド注入の前にインスタンス化する必要があるため、コンストラクターの実行中は注入ポイント エンジンが null のままであり、結果として NullPointerException が発生します。

この問題は次のいずれかの方法で解決できます JSR-330 Java の依存関係の注入 コンストラクター インジェクション、または Java @PostConstruct メソッド アノテーションの JSR 250 Common Annotations。

@PostConstruct

JSR-250 は、Java SE 6 に含まれているアノテーションの共通セットを定義します。

PostConstruct アノテーションは、 依存関係の挿入が行われた後に実行され、 初期化。このメソッドは、クラスが配置される前に呼び出さなければなりません(MUST) サービスに。このアノテーションは、次のようなすべてのクラスでサポートされなければなりません(MUST)。 依存関係の挿入をサポートします。

JSR-250 チャプター2.5 javax.annotation.PostConstruct

@PostConstruct アノテーションを使用すると、インスタンスがインスタンス化され、すべての注入が実行された後に実行されるメソッドの定義が可能になります。

public class Car {
  @Inject
  private Engine engine;  

  @PostConstruct
  public void postConstruct() {
    engine.initialize();  
  }
  ...
} 

コンストラクターで初期化を実行する代わりに、コードは @PostConstruct アノテーションが付けられたメソッドに移動されます。

構築後のメソッドの処理は、 @PostConstruct アノテーションが付けられたすべてのメソッドを見つけて、それらを順番に呼び出すという簡単な作業です。

private  void processPostConstruct(Class type, T targetInstance) {
  Method[] declaredMethods = type.getDeclaredMethods();

  Arrays.stream(declaredMethods)
      .filter(method -> method.getAnnotation(PostConstruct.class) != null) 
      .forEach(postConstructMethod -> {
         try {
           postConstructMethod.setAccessible(true);
           postConstructMethod.invoke(targetInstance, new Object[]{});
        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {      
          throw new RuntimeException(ex);
        }
      });
}

構築後のメソッドの処理は、インスタンス化と注入が完了した後に実行する必要があります。

また、初期化は、プロキシやリモーティングのいくつかの種類が関与しているときは常に意図したとおりに動作しませんベースのコンストラクタ。

CTはEJBがデシリアライズされますたびに呼び出されます、そして新しいプロキシが、それ...

のために作成されますたび
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top