2013-01-24 19 views
10

Javaでは、Java EE(CDI)プロキシの元のクラスオブジェクトおよび/またはクラス名をどのように取得しますか?プロキシのオリジナルクラス名(手作業による文字列操作なし)

プロキシインスタンスでgetName()を使用して、返された名前がある

com.company.employeemgmt.EmployeeManager$Proxy$_$$_WeldSubclass 

ようなものがでいくつかのfunctionaliyがあるのJava SE(7)またはEE(6)の元、unproxiedクラスのインスタンスのいずれかを返すようまたはその名前?

私は必要があります。もちろん

com.company.employeemgmt.EmployeeManager 

を、私は単純に文字列操作を使用することができますが、私はそのような機能がすでにJavaベース(EE)-inbuiltであるかどうかを知りたいです。 ...

public static void doSomething(Class<? implements Serializable> managerClass) 
{ 
    if (Proxy.isProxyClass(managerClass)) 
    { 
     // unproxy how? 
     managerClass = managerClass.getUnproxiedClass(); 
    } 

    // delegate 
    doSomething(managerClass.getName()); 
} 


public static void doSomething(String prefix) 
{ 
    // do real work 
    ... 
} 

が、どのように元のクラスを間接参照になります。

私はすでに、私はプロキシを検出するために使用することができjava.reflect.Proxyを見つけましたか?

更新:

トリックはMyUtil.doSomething(EmployeeManager.class)(またはMyUtil.doSomething(EmployeeManager.class.getName()))にアクセスすることですが、このコードは手動で変更することなく、周りにコピーすることができるように私は/使用するすべてのクライアントからMyUtil.doSomething(this.getClass())(またはMyUtil.doSomething(this.getClass().getName()))を渡したいです。

+0

private Class<?> findProxiedClass(Object proxiedObject) { Class<?> proxiedClass = proxiedObject.getClass(); if (proxiedObject instanceof Proxy) { Class<?>[] ifaces = proxiedClass.getInterfaces(); if (ifaces.length == 1) { proxiedClass = ifaces[0]; } else { // We need some selection strategy here // or return all of them proxiedClass = ifaces[ifaces.length - 1]; } } return proxiedClass; } 

テスト、それはあなたがしようとしましたmanagerClass.getDeclaringClass()またはmanagerClass.getEnclosingClass()? – jdb

+0

両方ともnullを返します。 – Kawu

+0

あなたがここで行うことは、移植性があり安定していません。プロキシは実際には他のクラスにのみ関連しています。CDIは、どの技術がプロキシに使用されているか、あるいはプロキシからクラスの詳細(マネージドBeanのBeanManager APIから始めることはできますが、オブジェクトから後方に進むことはできません)には何もしません。 – covener

答えて

4

これはに依存します。 Proxy.getInvocationHandler(manager)を使用して、プロキシのInvocationHandlerを取得できます。悲しいかな、InvocationHandlerは1つのinvokeメソッドしかなく、ターゲットクラスを取得できる機能がないインターフェイスです。それはすべて実装に依存します。

CXFウェブservcieフレームワークはClientを持っており、関連する呼び出しハンドラとしてClientProxyを使用する例として、次のようなクライアントを取得することができます:傷害に侮辱を追加するには

ClientProxy handler = (ClientProxy)Proxy.getInvocationHandler(proxiedObject); 
Client client = handler.getClient(); 

を、それがいるようですWeldInvocationHandlerを使用している可能性が高いのは、org.jboss.wsf.spi.invocation.InvocationHandlerへの代理を委任し、その代理人をプライベートフィールドに格納することです。したがって、ターゲットオブジェクトの実際のクラスを見つけるためには、リフレクションを使ってかなりの魔法を実行する必要があります。

2

プロキシクラスは元のクラスを継承しているので、プロキシスーパークラスを取得することで元のクラスを取得できると思います。

0

プロキシはそれを代理するインターフェイスなので、Class<?>[] Class.getInterfaces() を使用して、プロキシされたクラスを見つけることができます。

@Test 
public void testProxies() { 

    InvocationHandler handler = new InvocationHandler() { 
     @Override 
     public Object invoke(Object proxy, Method method, Object[] args) 
       throws Throwable { 
      return null; 
     } 
    }; 

    RandomAccess proxiedIface = (RandomAccess) Proxy.newProxyInstance(
      RandomAccess.class.getClassLoader(), 
      new Class[] { RandomAccess.class }, 
      handler); 

    Assert.assertEquals(RandomAccess.class, findProxiedClass(proxiedIface)); 
    Assert.assertEquals(Object.class, findProxiedClass(new Object())); 
}