10

在 Java 中,如何获取 Java EE (CDI) 代理的原始类对象和/或类名?

在代理实例上使用getName()时,返回的名称类似于

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

Java SE (7) 或 EE (6) 中是否有一些功能会返回原始的、未代理的类实例或其名称?

我需要:

com.company.employeemgmt.EmployeeManager

当然,我可以简单地使用字符串操作,但我想知道这样的功能是否已经是 Java-(EE) 内置的。

我已经找到了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() )),因为无需手动更改即可复制此代码。

4

3 回答 3

5

由于代理类继承自原始类,我认为可以通过获取代理超类来获取原始类。

于 2014-03-18T06:37:49.217 回答
4

这取决于. 您可以使用Proxy.getInvocationHandler(manager)获取代理的InvocationHandler。唉,InvocationHandler 是一个只有一个方法的接口,没有让你获得目标类的功能;这一切都取决于实施。invoke

例如,CXF web servcie 框架有一个Client并使用ClientProxy作为关联的调用处理程序,您可以这样获取 Client:

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

雪上加霜的是,您可能正在使用的WeldInvocationHandler似乎只是将调用委托给org.jboss.wsf.spi.invocation.InvocationHandler,它将其委托存储在私有字段中。所以你需要用反射做一些魔法来找出目标对象的实际类。

于 2013-01-25T11:57:06.723 回答
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()));
}
于 2015-05-03T13:29:39.500 回答