我上课
@RequestScoped
public class AFactory {
private final HttpServletRequest request;
protected AFactory () {
this.request = null;
}
@Inject
public AFactory (HttpServletRequest request) {
this.request = request;
}
@Produces
public A getA() {
int random = ...;
A a = new A(request);
a.setRandom(random);
return a;
}
}
我了解,因为我正在执行新的A(),所以我返回了真实实例。
这是使用生产者的预期方式吗?
有没有办法返回代理实例?
答案 0 :(得分:3)
CDI为proxies以外的所有范围的bean安装@Dependent
pseudo scope。每当需要获取bean的(新)实例时,CDI就会调用一个带有@Produces
注释的方法(简称 producer )。然后,将此实例放入对应范围的某个池中。
代理将始终从池中返回bean实例。尝试将一些调试消息添加到生产方方法,以查看其调用频率。 @ApplicationScoped
bean的生产者仅应被调用一次,@RequestScoped
生产者应在每个请求中被调用一次。
在上面的示例中,生产者方法未指定范围(生产者方法未使用factory类的范围),因此将使用默认范围(@Dependent)。这意味着(由于该范围没有使用代理),每次CDI找到@Inject A
时都会注入一个新实例。另请参阅此Question and Answer和参考文档以了解更多详细信息。
对于您的具体问题:
@Dependet
时才使用代理。答案 1 :(得分:-1)
编辑:尽管这个答案不正确(它可以解决CDI行为,而不是以CDI方式解决,但我已经有了某种免责声明; -))我会留在这里作为其他人的参考
您每次都会获得一个新实例,因为这是您在吸气剂中所做的。据我所知,一种@Produces
带注释的方法是有效注入的,它充当“代理”。因此,如果您希望每次在某处使用A都具有相同的A实例,则有两个选择
在构造函数中实例化A
private A a = null;
@Inject
public AFactory (HttpServletRequest request) {
this.request = request;
int random = ...;
a = new A(request);
a.setRandom(random);
}
@Produces
public A getA() {
return a;
}
或者在吸气剂中偷懒
private A a = null;
@Inject
public AFactory (HttpServletRequest request) {
this.request = request;
}
@Produces
public A getA() {
if (a==null) {
int random = ...;
a = new A(request);
a.setRandom(random);
}
return a;
}
就像在纯Java中一样,当您希望每次调用getter都返回相同的对象时。