BeanManager总是返回相同的引用 [英] BeanManager always returns same reference

查看:146
本文介绍了BeanManager总是返回相同的引用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在创建一个自定义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 @Injected 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆