2013-01-24 47 views
10

在Java中,如何獲取Java EE(CDI)代理的原始類對象和/或類名?代理的原始類名(無需手動字符串操作)

當代理實例使用getName(),返回的名稱是一樣的東西

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

是否有一些functionaliy的Java SE(7)或EE(6)將返回原來的,非代理類實例或它的名字?

我需要:

com.company.employeemgmt.EmployeeManager 

當然,我可以簡單地使用字符串操作,但我想知道如果這樣的功能已經是Java的(EE)-inbuilt。

我已經找到java.reflect.Proxy,我可以用它來檢測代理:

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

...,但你會如何取消引用原班?

更新:

訣竅將訪問MyUtil.doSomething(EmployeeManager.class)(或MyUtil.doSomething(EmployeeManager.class.getName())),但我想用/通過從所有客戶MyUtil.doSomething(this.getClass())(或MyUtil.doSomething(this.getClass().getName())),因爲這代碼周圍沒有手動更改被複制。

+0

測試它你嘗試managerClass.getDeclaringClass()或managerClass.getEnclosingClass()? – jdb

+0

它們都返回null。 – Kawu

+0

你在這裏沒有什麼是便攜或穩定的。代理實際上只與另一個類「相關」。CDI並不指定使用什麼技術進行代理或以任何方式從代理獲取Managed Bean的Class細節(儘管您可以從BeanManager API開始並向前工作而不是從Object向後) – covener

回答

4

它取決於。您可以使用Proxy.getInvocationHandler(manager)獲取代理InvocationHandler。唉,InvocationHandler是一個只有一個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() 找出代理類。

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

@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())); 
}