@PostConstruct を使用する理由
-
25-09-2019 - |
質問
マネージド 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メソッドが@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がデシリアライズされますたびに呼び出されます、そして新しいプロキシが、それ...
のために作成されますたび