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

2022-09-04 20:50:54

在 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);

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

我记得使用CDI方法阅读了一些关于潜在内存泄漏的内容,但不了解这种情况是如何或为什么会这样。


答案 1

这两种方法产生相似的结果,但是,有两个主要区别。

  • CDI.current()是你可以的东西,你不能简单地.@Inject BeanManager
    • 这只是从非 cdi 托管对象获取 CDI 实例的一种方法
  • Instance.get()不采用参数,而采用参数。CreationalContextBM.getReference()
    • 这是一个关键的区别,因为当使用时,是由容器管理的 - 你不需要关心它,特别是关于释放上下文。如果您正在使用,您首先需要获取该上下文,这通常意味着创建它,并且要求您负责在完成处理后也释放它。InstanceCreationalContextBM.getReference()

答案 2

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

JNDI 查找在 CDI 1.0 中使用。在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回声系统上进行非常基本的操作。如果您只想访问实例,这显然不是最佳解决方案。这就是为什么在 CDI 1.1 中,我们引入了抽象的 CDI 类,它使用 Java 服务加载程序从实现中检索具体的 CDI 类。...检索实例变得简单如下

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

推荐