@Produces不返回cdi代理,而是真实实例

时间:2019-05-07 14:11:00

标签: cdi factory

我上课

@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(),所以我返回了真实实例。

这是使用生产者的预期方式吗?

有没有办法返回代理实例?

2 个答案:

答案 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都返回相同的对象时。

相关问题