请解释CDI中的@Produces注释

时间:2013-05-14 03:40:54

标签: java java-ee cdi

我已经阅读了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生成器方法?

我也没有看到解决所有麻烦的原因。

2 个答案:

答案 0 :(得分:66)

CDI specification的第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 for products还显示了一个有趣的(但相当罕见的情况)生成一个命名集合,以后可以将其注入其他托管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的注入点解析的一部分。

答案 1 :(得分:1)

这个例子并不适合我。什么dit工作是一个小调整:

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

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

所以我必须在课堂上添加 @Alternative ,以摆脱 @Default 有两个选项的错误。