シングルトンアプローチに従って実装されたクラスにロガーオブジェクトを挿入しようとしています。
コードはほぼ次のようになります。
Logger
クラス:
public class LoggerFactory {
@Produces
public Logger getLogger(InjectionPoint caller){
return Logger.getLogger(caller.getMember().getDeclaringClass().getName());
}
}
次に、ロガーを必要とし、シングルトンパターンを実装するクラスを作成します。
public class MySingleton{
@Inject
private Logger logger;
private MySingleton instance;
/*
* Private constructor for singleton implementation
*/
private MySingleton(){
logger.info("Creating one and only one instance here!");
}
public MySingleton getInstance(){
if(instance == null) {
instance = new MySingleton();
}
return instance;
}
}
(Glassfish 3.1.2.2で)コードを実行すると、ロガーを使おうとするとすぐにNPEが表示されます。私が間違っていること(beans.xml
ファイルが配置されている)?また、Logger
オブジェクトのsetterメソッドで@Inject
を使用してみましたが、うまくいきませんでした。
注入は構築後に行われます。したがって、コンストラクターで使用することはできません。
1つの方法は、注入後に呼び出すことができる@PostConstructアノテーションが付けられたメソッドを追加することです。
@PostConstruct
public void init() {
logger.info("Creating one and only one instance here!");
}
ちなみに、私はあなたが間違った方法で問題を引き起こしていると思います。 CDIはニースシングルトンをサポートしています
@Singletonアノテーションが付けられたクラスを作成します
@Singleton
public class MySingleton {
@Inject
Logger logger;
@PostConstruct
public void init() {
logger.info("Creating one and only one instance here!");
}
}
上記は、Java ee(JSR-299)にCDIを使用していることを前提としています。
JSR 330依存性注入(guiceなど)を使用している場合 リンク
コンストラクタインジェクションを使用できます。
@Singleton
public class MySingleton {
private final Logger logger;
@Inject
public MySingleton (Logger logger) {
this.logger = logger;
logger.info("Creating one and only one instance here!");
}
}
すでに述べたように、コンストラクターが呼び出された後にインジェクションが実行されるため、これは機能しません。
@PostConstruct
アノテーションが付けられたメソッドは、インジェクションが終了した後、オブジェクト自体が別の場所に提供される前に呼び出されます。
ただし、インジェクションは、クラスのインスタンスがインジェクション自体によって提供される場合にのみ機能します。これは、プロキシに依存するインジェクションによるものです。
したがって、MySingletonを必要な場所に注入する必要があります。シングルトンであることを確認するには、@Singleton
に注釈を付けてください。そうすれば、コンテナーがそれを処理します。
さらに、CDI仕様に関するシングルトンは、@PostConstruct
の1つのインスタンス化だけではなく、1つの初期化を意味することに注意してください。