web-dev-qa-db-ja.com

シングルトンパターンでのCDIの使用

シングルトンアプローチに従って実装されたクラスにロガーオブジェクトを挿入しようとしています。

コードはほぼ次のようになります。

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を使用してみましたが、うまくいきませんでした。

14
fabpicca

注入は構築後に行われます。したがって、コンストラクターで使用することはできません。

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!");
    }
}
22
Aksel Willgert

すでに述べたように、コンストラクターが呼び出された後にインジェクションが実行されるため、これは機能しません。

@PostConstructアノテーションが付けられたメソッドは、インジェクションが終了した後、オブジェクト自体が別の場所に提供される前に呼び出されます。

ただし、インジェクションは、クラスのインスタンスがインジェクション自体によって提供される場合にのみ機能します。これは、プロキシに依存するインジェクションによるものです。

したがって、MySingletonを必要な場所に注入する必要があります。シングルトンであることを確認するには、@Singletonに注釈を付けてください。そうすれば、コンテナーがそれを処理します。

さらに、CDI仕様に関するシングルトンは、@PostConstructの1つのインスタンス化だけではなく、1つの初期化を意味することに注意してください。

4
omilke