请解释CDI中的@Produces注解

Posted

技术标签:

【中文标题】请解释CDI中的@Produces注解【英文标题】:Please explain the @Produces annotation in CDI 【发布时间】:2013-05-08 05:38:41 【问题描述】:

我读过 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 生产者方法?

我也看不出经历所有麻烦的原因。

【问题讨论】:

【参考方案1】:

这个例子对我不太适用。它的工作是一个小调整:

@Alternative
class SomeTPLClass 
    public SomeTPLClass(String id) 
    


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

所以我不得不在我的班级中添加 @Alternative 以消除 @Default 有两个选项的错误。

【讨论】:

【参考方案2】:

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

【讨论】:

不错的答案。谢谢。但我对你的第一个例子有疑问。可以说Class C@ProducesEntityManagerClass B从哪里知道从这些注入哪个? @Produces 只能被 Class 使用一次 @Perception - 我非常感谢您在这里所做的努力,我认为您添加了很棒的内容。但是,对于 JavaEE 新手,我仍然看不到注释的作用?在使用 EntityManager 的第一个示例中,为什么添加此注释使其可以使用 @Inject?另外,“生产者方法充当要注入的对象的来源”到底是什么意思?成为对象的来源是什么意思? @Inject 表示您可以使用该对象而无需手动创建它。 @Produres 是您创建它的地方。而对于 EntityManager,我认为 jboss 使用 @PersistenceContext 为您创建它

以上是关于请解释CDI中的@Produces注解的主要内容,如果未能解决你的问题,请参考以下文章

哪个是 CDI @Produces 注释的 Spring 等效项?

springmvc 没有produces注释

SpringMVC注解@RequestMapping之produces属性导致的406错误

EJB 的 CDI 生产者

springmvc返回xml格式json格式数据

解决@ResponseBody注解返回中文乱码