【发布时间】:2013-12-01 15:21:39
【问题描述】:
我认为,当只有Bean<T> 开头(基于Class<T> 创建)时,有两种通用方法可以通过BeanManager 获取自动创建的CDI 托管bean 实例:
-
作者
BeanManager#getReference(),更常见于 sn-ps:Bean<TestBean> bean = (Bean<TestBean>) beanManager.resolve(beanManager.getBeans(TestBean.class)); TestBean testBean1 = (TestBean) beanManager.getReference(bean, bean.getBeanClass(), beanManager.createCreationalContext(bean)); -
Context#get(),在 sn-ps 中很少出现:Bean<TestBean> bean = (Bean<TestBean>) beanManager.resolve(beanManager.getBeans(TestBean.class)); TestBean testBean2 = beanManager.getContext(bean.getScope()).get(bean, beanManager.createCreationalContext(bean));
实际上,它们最终做的事情完全相同:返回对当前 CDI 托管 bean 实例的代理引用,如果该 bean 实例在作用域中不存在,则自动创建它。
但他们的做法有点不同:BeanManager#getReference() 总是创建一个全新的代理实例,而 Context#get() 重用现有的代理实例(如果之前已经创建)。当上述代码在现有TestBean 实例的操作方法中执行时,这一点很明显:
System.out.println(testBean1 == testBean2); // false
System.out.println(testBean1 == this); // false
System.out.println(testBean2 == this); // true
Context#get() 的 javadoc 在这方面非常明确:
返回某个上下文类型的现有实例或通过调用 Contextual.create(CreationalContext) 创建一个新实例并返回新实例。
虽然BeanManager#getReference() 的javadoc 在这方面不够明确:
获取某个bean的上下文引用以及该bean的某个bean类型。
这让我很困惑。你什么时候使用一个或另一个?对于这两种方式,您无论如何需要一个Bean<T> 实例,bean 类和bean 范围很容易从中获得,这是作为附加参数所必需的。我无法想象为什么在这种特定情况下需要从外部提供它们。
我可以想象Context#get() 的内存效率更高,因为它不会不必要地创建另一个引用相同底层 bean 实例的代理实例,而只是查找并重用现有的代理实例。
这让我想到了以下问题:BeanManager#getReference() 究竟什么时候比Context#get() 更有用?它更常显示在 sn-ps 中,并且更经常被推荐为解决方案,但它只会不必要地创建一个新代理,即使已经存在一个代理。
【问题讨论】:
标签: cdi managed-bean