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 はメソッドが 1 つしかないインターフェイスであり、ターゲット クラスを取得できる機能はありません。それはすべて実装に依存します。invoke

たとえば、CXF Web サービス フレームワークには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 に答える