请解释 CDI 中@Produces注释

2022-08-31 17:35:38

我已经阅读了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-

容器如何知道调用生产者方法?如果我注入一个实体管理器,容器如何调用@produces实体管理器?如何调用 getLogger 生产者方法?

我也看不出有什么理由去经历所有的麻烦。


答案 1

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 的注入点分辨率的一部分。


答案 2

这个例子对我不太管用。dit的工作原理是一个小的调整:

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

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

因此,我不得不在我的课堂上添加@Alternative,以摆脱@Default有两个选项的错误


推荐