2017-02-15 9 views
1

カスタムCDIスコープを作成していて、BeanManagerを使用してNavigationHandlerカスタムクラスの注入を取得しています。しかし、それが返す豆はかなり奇妙です。BeanManagerは常に同じ参照を返します

だから私は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()+")"); 
     return reference; 
    } 
    ... 
} 

私はそのように定義されている2つの異なるNavigationHandlerを取得するには、二つの異なるブラウザを使用して、私のプロジェクトを使用する場合、私は、期待:

@Named 
@WindowScoped 
public class NavigationHandler 
    implements Serializable, INavigationHandlerController 

しかし、reference1==reference2をテストすると、デバッガはtrueを返します。また、私は奇妙なハッシュコードを取得する:

Found [email protected] (hash=1261587818) 
Found [email protected] (hash=1261587818) 
のtoString()で使用されるハッシュが異なっている理由を私は理解していない

が、ハッシュコードで使用されるハッシュは、()と同じです。

答えて

1

私はこれらの2つのリンクされた問題の理由を考え出したと思います。それは難しい問題でした。

m_beanManager.getReference(..)は、NavigationHandlerインスタンスを返しませんが、スコープのコンテキストで既存のNavigationHandlerを選択して正しいNavigationHandlerとして機能させるプロキシを返します。

リンクは、プロキシ/コンテキスト/ BeanManagerの概念を理解する:https://developer.jboss.org/blogs/stuartdouglas/2010/10/12/weld-cdi-and-proxies

だから私のgetNavigationHandler()方法は仕事には適していません。私のプールNavigationHandlerプロキシの代わりNavigationHandlersを保持する、このメソッドを呼び出します。私のプールは@Inject edフィールドではないので、プロキシはCDIによって自動的に更新されません。したがって、返される参照は、常にプロキシによって積極的に使用される最後のコンテキストのものです。

この出力では、同様の理由:1の場合

Found [email protected] (hash=1261587818) 
Found [email protected] (hash=1261587818) 

私はNavigationHandlerインスタンスのハッシュを取得し、それ以外の場合には、私はNavigationHandlerのプロキシのハッシュを取得します。しかし、私はどちらがどちらであるかわからない。私はbeanManager.getReference(..)が毎回新しいプロキシを提供することになっているので、プロキシのtoString()が使用されていると考えています。hashCodeはオブジェクトごとに事実上一意であると考えられています。すべてのインスタンスのハッシュコードは、独自のハッシュコードであり、時間とともに変化することはできませんと言う

リンク:http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#hashCode%28%29

のでgetNavigationHandler()を実装するための正しい方法は次のとおりです。の違いを説明

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; 
} 

リンクbeanManager.getReference(..)およびbeanManager.getContext(..).get(..)Canonical way to obtain CDI managed bean instance: BeanManager#getReference() vs Context#get()

関連する問題