CDI.current().select().get() 和 BeanManager.getReference() 功能等效吗?

问题描述 投票:0回答:2

在 JEE/CDI 的上下文中,当我需要从方法中静态检索 CDI 托管 bean 时,我发现自己通常使用 CDI 静态函数。 例如:

MyBean myBean = CDI.current().select( MyBean.class ).get()

但是,据我所知,实现此目的的另一种等效方法是使用 BeanManager:

BeanManger bm = new InitialContext().lookup( "java:comp/BeanManager" );
Bean<?> bean = bm.resolve(bm.getBeans( MyBean.class ) );
CreationalContext<?> context = bm.createCreationalContext(bean);
MyBean myBean = bm.getReference(bean, cls, context);

那么,除了使用

CDI.current()
方法编写的代码明显减少之外,使用它还有什么区别呢? 恢复使用
BeanManager
似乎是一种更加复杂(并且可能容易出错?)的方法。 从功能角度来看,使用
CDI.current()
方法有什么缺点吗?
CDI...select()
只适用于
@ApplicationScope
bean 吗? 或者我也可以与其他作用域 bean 一起使用(例如:
@Dependent
)吗?

我记得读过一些有关使用 CDI 方法潜在内存泄漏的内容,但不明白如何或为什么会出现这种情况。

java jakarta-ee cdi
2个回答
13
投票

两种方法产生相似的结果,但是,存在两个主要差异。

  • CDI.current()
    是当您无法简单地
    @Inject BeanManager
    时可以做的事情。
    • 这只是从非 CDI 托管对象获取 CDI 实例的一种方法
  • Instance.get()
    不采用
    CreationalContext
    参数,而
    BM.getReference()
    则采用。
    • 这是一个至关重要的区别,当使用
      Instance
      时,
      CreationalContext
      由容器管理 - 你不需要关心它,尤其是释放上下文。如果您正在使用
      BM.getReference()
      ,您首先需要获取该上下文,这通常意味着创建它,并且您有责任在完成使用它后释放它。

8
投票

我们使用这些方法在非 CDI 代码中访问 CDI。在 CDI 代码中,我们可以注入 BeanManager 和您的 beans。

CDI 1.0 中使用 JNDI 查找。在 CDI 1.1 之后,我们应该使用 CDI 类及其静态方法。

http://www.next-presso.com/2016/02/cdi-the-spi-who-loved-me/

在 CDI 1.0 中,访问 CDI bean 图的唯一解决方案是从 JNDI 检索 BeanManager ... 这种冗长证明了 BeanManager 是先进的 CDI 工具,允许在 CDI echos 系统上进行非常基本的操作。如果您只想访问实例,这显然不是最好的解决方案。 这就是为什么在 CDI 1.1 中我们引入了抽象 CDI 类,它使用 Java Service Loader 从实现中检索具体的 CDI 类。 ... 检索实例变得如此简单

CDI<Object> cdi = CDI.current();
MyService service = cdi.select(MyService.class).get();
© www.soinside.com 2019 - 2024. All rights reserved.