Java8动态代理和默认方法 [英] Java8 dynamic proxy and default methods

查看:916
本文介绍了Java8动态代理和默认方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

拥有使用默认方法的接口的动态代理,如何调用默认方法?通过使用像 defaultmethod.invoke(this,...)之类的东西,你只需要调用你的代理调用处理程序(这在某种程度上是正确的,因为你没有这个接口的实现类)。

Having a dynamic proxy for an interface with default methods, how do I invoke a default method? By using something like defaultmethod.invoke(this, ...) you just get your proxy invocation handler called (Which is somehow correct, cause you have no implementing class for this interface).

我有一个解决方法,使用ASM创建一个实现接口的类,并将这些调用委托给这个类的实例。但这不是一个好的解决方案,特别是如果默认方法调用其他接口方法(你得到一个委托人ping-pong)。对于这个问题,JLS出乎意料地保持沉默...

I have a workaround using ASM to create a class implementing the interface and delegating such calls to an instance of this class. But this is not a good solution, especially if the default method calls other interface methods (you get a delegator ping-pong). The JLS is surprisingly silent about this question...

这里有一个小代码示例:

Here a small code example:

public class Java8Proxy implements InvocationHandler {
    public interface WithDefaultMethod {
        void someMethod();

        default void someDefaultMethod() {
            System.out.println("default method invoked!");
        }
    }

    @Test
    public void invokeTest() {
        WithDefaultMethod proxy = (WithDefaultMethod) Proxy.newProxyInstance(
            WithDefaultMethod.class.getClassLoader(),
            new Class<?>[] { WithDefaultMethod.class }, this);
        proxy.someDefaultMethod();

    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        // assuming not knowing the interface before runtime (I wouldn't use a
        // proxy, would I?)
        // what to do here to get the line printed out?

        // This is just a loop
        // method.invoke(this, args);

        return null;
    }
}


推荐答案

你可以使用 MethodHandles 类型你的 InvocationHandler 。此代码复制自零周转

You can use the MethodHandles type in your InvocationHandler. This code is copied from Zero Turnaround.

Constructor<MethodHandles.Lookup> constructor;
Class<?> declaringClass;
Object result;

if (method.isDefault()) {
   declaringClass = method.getDeclaringClass();
   constructor = MethodHandles.Lookup.class.getDeclaredConstructor(Class.class, int.class);

   constructor.setAccessible(true);

   result = constructor.
      newInstance(declaringClass, MethodHandles.Lookup.PRIVATE).
      unreflectSpecial(method, declaringClass).
      bindTo(proxy).
      invokeWithArguments(args);

   return(result);
}

这篇关于Java8动态代理和默认方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆