我已经阅读了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生成器方法?
我也没有看到解决所有麻烦的原因。
答案 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 有两个选项的错误。