web-dev-qa-db-ja.com

CDIで@Producesアノテーションを説明してください

CDIの@Producesアノテーションについて読んだことがありますが、その使用法がわかりません。

public class Resources {

// Expose an entity manager using the resource producer pattern
@SuppressWarnings("unused")
@PersistenceContext
@Produces
private EntityManager em;                                        // 

@Produces
Logger getLogger(InjectionPoint ip) {                            // 
    String category = ip.getMember()
                        .getDeclaringClass()
                        .getName();
    return Logger.getLogger(category);
}

@Produces
FacesContext getFacesContext() {                                 // 
    return FacesContext.getCurrentInstance();
}

}

以下から取得: http://www.jboss.org/jdf/quickstarts/jboss-as-quickstart/guide/GreeterQuickstart/#GreeterQuickstart-

コンテナはどのようにしてプロデューサーメソッドを呼び出すことを知っていますか? EntityManagerを注入する場合、コンテナはどのようにして@produces EntityManagerを呼び出しますか?そして、getLoggerプロデューサーメソッドはどのように呼び出されますか?

また、すべてのトラブルを経験する理由もわかりません。

40
user798719

CDI仕様 のセクション3.3は、 @Produces アノテーションの使用に関するかなり高レベルの概要を示しています。

プロデューサーメソッドは、注入されるオブジェクトのソースとして機能します。

•注入されるオブジェクトは、Beanのインスタンスである必要はありません。または
•注入されるオブジェクトの具体的なタイプは、実行時に異なる場合があります。
•オブジェクトには、Beanコンストラクターによって実行されないカスタム初期化が必要です。

たとえば、JavaエンティティマネージャなどのEE管理コンポーネントと他のCDIコンポーネントをブリッジしたい場合、@Producesアノテーションを利用できます。データドメインレイヤー全体で@PersistenceContextアノテーションを複製する必要がなくなります。

class A {
    @PersistenceContext       // This is a JPA annotation
    @Produces                 // This is a CDI 'hook'
    private EntityManager em; 
}

class B {
   @Inject                    // Now we can inject an entity manager
   private EntityManager em;
}

別の便利な使用法は、CDIフレンドリBeanを持たないライブラリを回避することです(たとえば、デフォルトコンストラクターがない)。

class SomeTPLClass {
    public SomeTPLClass(String id) {
    }
}

class SomeTPLClassProducer {
    @Produces
    public SomeTPLClass getInstance() {
        return new SomeTPLClass("");
    }
}

プロデュースのJavadocは、後で他のマネージドBeanにインジェクトでき​​る名前付きコレクションを作成するという興味深い(ただし非常にまれなケース)を示しています(非常にクールです)。

public class Shop { 
    @Produces @ApplicationScoped 
    @Catalog @Named("catalog") 
    private List<Product> products = new LinkedList<Product>(8);

    //...
}

public class OrderProcessor {
    @Inject
    @Catalog
    private List<Product> products;
}

コンテナは、@ Producesアノテーションでマークされたすべてのメソッドとフィールドの処理を担当し、通常、アプリケーションのデプロイ時にこれを行います。処理されたメソッドとフィールドは、必要に応じて、マネージドBeanの注入ポイント解決の一部として使用されます。

68
Perception

この例は私にとってはうまくいきませんでした。ちょっとした調整はちょっとした微調整でした:

@Alternative
class SomeTPLClass {
    public SomeTPLClass(String id) {
    }
}

class SomeTPLClassProducer {
    @Produces
    public SomeTPLClass getInstance() {
        return new SomeTPLClass("");
    }
}

そのため、クラスに@ Alternativeを追加して、@ Defaultに2つのオプションがあったというエラーを取り除く必要がありました。

1
Hans