BeanManager总是返回相同的引用 [英] BeanManager always returns same reference
问题描述
我正在创建一个自定义CDI范围,并使用 BeanManager
来注入我的 NavigationHandler
自定义类。但是它返回的bean是很奇怪的。
所以我使用BeanManager:
public class ScreenContext implements Context
{
private NavigationHandler getNavigationHandler()
{
final Set< Bean<>> beans = m_beanManager.getBeans(NavigationHandler.class);
final Bean<?> bean = m_beanManager.resolve(beans);
NavigationHandler reference =
(NavigationHandler)m_beanManager.getReference(bean,NavigationHandler.class,
m_beanManager.createCreationalContext(bean));
System.out.println(Found+ reference +(hash =+ reference.hashCode()+));
返回参考;
}
...
}
我预计,我使用我的项目使用两种不同的浏览器,以获得两种不同的 NavigationHandler
,它们是这样定义的:
@Named
@WindowScoped
public class NavigationHandler
实现Serializable,INavigationHandlerController
但是当我测试 reference1 == reference2
时,我的调试器返回 true
。我也得到了奇怪的哈希码:
pre $ 找到NavigationHandler @ 593e785f(hash = 1261587818)
找到NavigationHandler @ b6d51bd(hash = 1261587818)
我不明白为什么toString()中使用的哈希值不同,但在hashCode()中使用的散列是相同的。
我想我找出了这两个链接问题的原因,是一个棘手的问题!
m_beanManager.getReference(..)
不会返回NavigationHandler实例,而是一个代理它应该选择并充当范围上下文中现有的NavigationHandler。
链接以了解代理/上下文/ BeanManager的概念: https://开发人员。 jboss.org/blogs/stuartdouglas/2010/10/12/weld-cdi-and-proxies
因此,我的 getNavigationHandler()
方法不适合这项工作:调用此方法的我的池将保存NavigationHandler代理,而不是NavigationHandlers 。由于我的池不是 @Inject
ed字段,所以代理不会被CDI自动更新,因此返回的引用始终是来自上一个上下文活动使用的引用代理。
出于同样的原因在这个输出中:
Found NavigationHandler @ 593e785f(hash = 1261587818)
找到NavigationHandler @ b6d51bd(hash = 1261587818)
在一种情况下,我得到了 NavigationHandler
实例的哈希,而在另一种情况下,我得到了 NavigationHandler
代理人。但我不知道哪一个是哪个。我愿意相信代理的toString()被使用,因为 beanManager.getReference(..)
应该每次都提供一个新的代理,并且hashCode应该是实际上每个实例对象都是唯一的。
链接表示每个实例的哈希码都是唯一的哈希码,并且不能随时间变化: http://docs.oracle.com/javase /7/docs/api/java/lang/Object.html#hashCode%28%29
所以实现 getNavigationHandler()
is:
private getNavigationHandlergetgetNavigationHandler()
{
final Set< Bean>> beans = m_beanManager.getBeans(getNavigationHandler.class);
final Bean<?> bean = m_beanManager.resolve(beans);
/ *工程:纯引用(未代理)* /
类<?扩展注释> scopeType = bean.getScope();
上下文上下文= m_beanManager.getContext(scopeType);
CreationalContext<?> creationalContext = m_beanManager.createCreationalContext(bean);
//因为继承不适用于模板,所以必须在下面进行投射
getNavigationHandler reference =
context.get((Bean< NavigationHandler>)bean,(CreationalContext< NavigationHandler>)creationalContext);
返回参考;
}
解释 beanManager.getReference(..)
和 beanManager.getContext(..)。get(..)
:标准方式获取CDI托管bean实例:BeanManager#getReference()vs Context#get()
I am creating a custom CDI scope and am using the BeanManager
to get an injection of my NavigationHandler
custom class. But the beans it returns are quite strange.
So I use the BeanManager that way :
public class ScreenContext implements Context
{
private NavigationHandler getNavigationHandler()
{
final Set<Bean<?>> beans = m_beanManager.getBeans(NavigationHandler.class);
final Bean<?> bean = m_beanManager.resolve(beans);
NavigationHandler reference =
(NavigationHandler) m_beanManager.getReference(bean, NavigationHandler.class,
m_beanManager.createCreationalContext(bean));
System.out.println("Found "+reference+" (hash="+reference.hashCode()+")");
return reference;
}
...
}
I expect, when I use my project using two different browsers, to get two different NavigationHandler
, which are defined that way :
@Named
@WindowScoped
public class NavigationHandler
implements Serializable, INavigationHandlerController
But my debugger returns true
when I test reference1==reference2
. I also get strange hash codes :
Found NavigationHandler@593e785f (hash=1261587818)
Found NavigationHandler@b6d51bd (hash=1261587818)
I don't understand why the hashes used in the toString() are different, but the hash used in hashCode() are the same.
I think I figured out the reason for these two linked problems, that was a tricky one !
m_beanManager.getReference(..)
does not return the NavigationHandler instance, but a proxy which is supposed to select and act as the correct NavigationHandler among the existing ones in the scope's context.
Link to understand the concept of Proxy/Context/BeanManager: https://developer.jboss.org/blogs/stuartdouglas/2010/10/12/weld-cdi-and-proxies
So my getNavigationHandler()
method is not suited for the work : my pool which calls this method will hold NavigationHandler proxies instead of NavigationHandlers. Because my pool is not an @Inject
ed field, the proxy will not get automatically updated by CDI, hence the reference returned is always the one from the last context actively used by a proxy.
For the same reason in this output:
Found NavigationHandler@593e785f (hash=1261587818)
Found NavigationHandler@b6d51bd (hash=1261587818)
In one case I get the hash of the NavigationHandler
instance, and in the other case I get the hash of the NavigationHandler
's proxy. Yet I don't know which one is which. I am willing to believe the proxy's toString() is used, as beanManager.getReference(..)
is supposed to serve a new proxy each time, and the hashCode is supposed to be practically unique for object each instances.
Link that says every instance's hashcode is unique hashcode and cannot change over time: http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#hashCode%28%29
So the correct way to implement getNavigationHandler()
is:
private getNavigationHandlergetgetNavigationHandler()
{
final Set<Bean<?>> beans = m_beanManager.getBeans(getNavigationHandler.class);
final Bean<?> bean = m_beanManager.resolve(beans);
/* Works : pure reference (not proxied) */
Class<? extends Annotation> scopeType = bean.getScope();
Context context = m_beanManager.getContext(scopeType);
CreationalContext<?> creationalContext = m_beanManager.createCreationalContext(bean);
// Casts below are necessary since inheritence does not work for templates
getNavigationHandler reference =
context.get((Bean<NavigationHandler>) bean, (CreationalContext<NavigationHandler>) creationalContext);
return reference;
}
Link that explains the difference between beanManager.getReference(..)
and beanManager.getContext(..).get(..)
: Canonical way to obtain CDI managed bean instance: BeanManager#getReference() vs Context#get()
这篇关于BeanManager总是返回相同的引用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!