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

时间:2018-10-29 14:48:30

标签: java java-ee cdi

在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方法阅读了有关潜在内存泄漏的内容,但不了解这种情况如何或为什么发生。

2 个答案:

答案 0 :(得分:1)

我们使用这些方法以您的非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 Service Loader从实现中检索具体的CDI类。       ...       检索实例变得如此简单

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

答案 1 :(得分:1)

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

  • CDI.current()是您可以做的事,而您不能简单地@Inject BeanManager
    • 这只是从非cdi受管对象中获取CDI实例的一种方式
  • Instance.get()不使用CreationalContext参数,而BM.getReference()则使用。
    • 这之间的关键区别在于,在使用Instance时,CreationalContext由容器管理-您不必关心它,尤其是释放上下文。如果您使用的是BM.getReference(),则首先需要获取该上下文,这通常意味着创建它,并使您有责任在完成使用后也将其释放。