CDI.current().select().get() 和 BeanManager.getReference() 在功能上是否等效?

Are CDI.current().select().get() and BeanManager.getReference() functionally equivalent?

在 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 方法可能发生内存泄漏的文章,但不明白为什么会出现这种情况。

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

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

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

In CDI 1.0 the only solution you had to access CDI bean graph was to retrieve the BeanManager from JNDI ... This verbosity is the proof that the BeanManager is and advanced CDI tool allowing very basic operation on CDI echos system. It’s obviously not the best solution if you just want to access an instance. That’s why, in CDI 1.1 we introduced the abstract CDI class which use Java Service Loader to retrieve a concrete CDI class from the implementation. ... Retrieving an instance becomes as simple as

CDI<Object> cdi = CDI.current();
MyService service = cdi.select(MyService.class).get();

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

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