2017-08-13 9 views
0

cdiでオブジェクトを自分自身に注入すると、すべてのインターセプタは削除されます。これは@ EJB-Injectionと大きな違いです。私のプロジェクトではejb-cdi-unit私はEjbsの注入にCDI手段を注入してシミュレートしようとしています。したがって、私はInjectionTargetを操作して既に存在するCDI-Extensionを拡張しようとします。CDI-extensionを使用して注入された "self"にインタセプタを作用させます。

ウェブでは、PropertyLoaderExtensionを例として、実際の注入が発生した時点でInjectionTargetを操作する方法を示しました。私が必要としないPropertiesymanipulatingものは、プロキシが呼び出されたときにインターセプタをアクティブにすることに興味があります。そのために、使用されたWeld-VersionはInterceptionDecorationContextに2つの静的関数を提供することが分かりました。だから私は、InterceptionDecorationContextへの呼び出しによって注入されたフィールドを通して各呼び出しをラップしたいと思います。 実際のラッピングを行うには、私はcglib-Enhancerを使用します。

インスタンスが挿入されるとすぐに、ラッピングが実行され、ラップされたオブジェクトが挿入されます。 Interceptorを持つBeanであるこのラップされたオブジェクトのメソッドを誰かが呼び出すと、InterceptionDecorationContextへのWeld固有の呼び出しがそれらをアクティブにする必要があります。リソースSessionContextがシミュレートされるコード内の別の場所では、すでに正常に動作しています。 SessionContextSimulation

@Override 
public <T> T getBusinessObject(Class<T> businessInterface) throws IllegalStateException { 
    Set<Bean<?>> beans = beanManager.getBeans(businessInterface); 
    if (beans.isEmpty() && businessInterface.getName().endsWith("_WeldSubclass")) { 
     beans = beanManager.getBeans(businessInterface.getSuperclass()); 
    } 
    Bean<T> bean = (Bean<T>) beanManager.resolve(beans); 

    final Object testBean1 = beanManager.getReference(bean, bean.getBeanClass(), beanManager.createCreationalContext(bean)); 

    Enhancer enhancer = new Enhancer(); 
    enhancer.setSuperclass(businessInterface); 
    enhancer.setCallback(new InvocationHandler() { 
     @Override 
     public Object invoke(Object o, Method method, Object[] objects) throws Throwable { 
      InterceptionDecorationContext.startIfNotEmpty(); 
      try { 
       return method.invoke(testBean1, objects); 
      } catch (Throwable thw) { 
       if (thw instanceof InvocationTargetException) { 
        throw thw.getCause(); 
       } else { 
        throw thw; 
       } 
      } 
      finally { 
       InterceptionDecorationContext.endInterceptorContext(); 
      } 
     } 
    }); 

    Object proxy = enhancer.create(); 

    return (T) proxy; 
} 

しかし:initializeSelfInitはなく、注入されたオブジェクトの呼び出し時に、それによって導入されたラッパーが溶接によって呼び出される、適切な場所に呼び出されます。 InterceptionTargetの取り扱いには誤解がなければなりません。

答えて

0

解決策が見つかりました。誤解は、パラメータインスタンスが注入されたBeanではなく、注入が行われるBeanです。 InjectionTarget.injectはインスタンスを取り、すべての注入を正しく埋めます。目標は、Weld(InjectionTargetのスーパークラス)に注入を行い、必要に応じて、フィールドをラップされたフィールドで置き換えることによって修正します。

InjectionTarget<T> wrapped = new InjectionTarget<T>() { 

      @Override 
      public void inject(final T instance, CreationalContext<T> ctx) { 
       it.inject(instance, ctx); 
       // After injection replace all fields of self-type by enhanced ones which make sure interception is handled. 
       for (AnnotatedField<? super T> f: pit.getAnnotatedType().getFields()) { 
        if (f.getJavaMember().getType().equals(pit.getAnnotatedType().getJavaClass())) { 
         try { 
          final Field javaMember = f.getJavaMember(); 
          javaMember.setAccessible(true); 
          final Object currentInstance = javaMember.get(instance); 
          Enhancer enhancer = new Enhancer(); 
          enhancer.setSuperclass(currentInstance.getClass()); 
          enhancer.setCallback(new InvocationHandler() { 
           @Override 
           public Object invoke(Object o, Method method, Object[] objects) throws Throwable { 
            SessionContextSimulation.startInterceptionDecorationContext(); 
            try { 
             return method.invoke(currentInstance, objects); 
            } catch (Throwable thw) { 
             if (thw instanceof InvocationTargetException) { 
              throw thw.getCause(); 
             } else { 
              throw thw; 
             } 
            } finally { 
             InterceptionDecorationContext.endInterceptorContext(); 
            } 
           } 
          }); 
          javaMember.setAccessible(true); 
          javaMember.set(instance, enhancer.create()); 
         } catch (IllegalAccessException e) { 
          throw new RuntimeException(e); 
         } 
        } 
       } 
      } 
関連する問題