我认为有两种通用方法可以获得一个自动创建的CDI托管bean实例BeanManager,只需要一个Bean<T>开始(基于它创建Class<T>):
通过BeanManager#getReference(),更经常以片段形式显示:
Bean<TestBean> bean = (Bean<TestBean>) beanManager.resolve(beanManager.getBeans(TestBean.class));
TestBean testBean1 = (TestBean) beanManager.getReference(bean, bean.getBeanClass(), beanManager.createCreationalContext(bean));
Run Code Online (Sandbox Code Playgroud)通过Context#get(),在片段中不常显示:
Bean<TestBean> bean = (Bean<TestBean>) beanManager.resolve(beanManager.getBeans(TestBean.class));
TestBean testBean2 = beanManager.getContext(bean.getScope()).get(bean, beanManager.createCreationalContext(bean));
Run Code Online (Sandbox Code Playgroud)实际上,它们最终完全相同:返回对当前CDI托管bean实例的代理引用,并自动创建bean实例(如果范围中尚不存在).
但是他们做的有点不同:BeanManager#getReference()总是创建一个全新的代理实例,而Context#get()如果之前已经创建过,则重用现有的代理实例.当在现有TestBean实例的action方法中执行上述代码时,这是显而易见的:
System.out.println(testBean1 == testBean2); // false
System.out.println(testBean1 == this); // false
System.out.println(testBean2 == this); // true
Run Code Online (Sandbox Code Playgroud)
该的javadoc的Context#get()是非常明确的在此:
返回某个上下文类型的现有实例,或通过调用Contextual.create(CreationalContext)创建一个新实例并返回新实例.
而javadoc中的BeanManager#getReference()不够明确在此:
获得某个bean和bean的某个bean类型的上下文引用.
这让我感到困惑.你什么时候使用这一个?对于这两种方式,无论如何都需要一个Bean<T>实例,bean类和bean范围随时可用,这是额外的参数.我无法想象为什么在这种特殊情况下他们需要外部供应.
我可以想象这Context#get()是更高效的内存,因为它不会不必要地创建引用同一个底层bean实例的另一个代理实例,而只是查找并重用现有的代理实例.
这让我想到了以下问题:什么时候BeanManager#getReference()更有用Context#get()呢?它通常以片段形式显示,更经常被推荐为解决方案,但它只会在不存在的情况下不必要地创建新的代理.
Asi*_*tto 36
beanManager#getReference为您提供了客户端代理的新实例,但客户端代理会将方法调用转发到特定上下文的当前上下文实例.获得代理并保留代理后,将在当前实例上调用方法调用(例如,当前请求).如果上下文实例不可序列化,它也很有用 - 客户端代理将在反序列化之后重新连接.
BeanManager#getContext获取没有客户端代理的目标实例.您仍然可以在类名中看到Weld的代理,但这是一个增强的子类,提供拦截和修饰.如果bean没有被拦截也没有装饰,那么这将是给定bean的普通实例.
通常(1)更合适,除非您有一个特殊的用例,您需要直接访问目标实例(例如访问其字段).
1)BeanManager#getReference将返回一个'Contextual Reference',其中包含bean的正常范围代理.如果一个bean有@SessionScopedas
@SessionScoped User user;
Run Code Online (Sandbox Code Playgroud)
然后,上下文引用用户将"指向" 每个调用的当前会话的相应用户实例("上下文实例").user.getName()来自两个不同Web浏览器的两种不同调用将为您提供不同的答案.
2)Context#get()将返回一个没有正常范围代理的内部'Contextual Instance'.这通常不是用户应该自称的.如果User user以这种方式获得"Bob"并将其存储在@ApplicationScopedbean或静态变量中,那么它将始终保持为用户"Bob" - 即使是来自其他浏览器的Web请求!您将获得一个直接的非代理实例.
| 归档时间: |
|
| 查看次数: |
13001 次 |
| 最近记录: |