Java8动态代理和默认方法

标签 java java-8

为具有默认方法的接口(interface)提供动态代理,我该如何调用默认方法?通过使用类似 defaultmethod.invoke(this, ...) 的方法,您只需调用代理调用处理程序(这在某种程度上是正确的,因为您没有此接口(interface)的实现类)。

我有一个解决方法,使用 ASM 创建一个实现接口(interface)的类,并将此类调用委托(delegate)给此类的一个实例。但这不是一个好的解决方案,特别是如果默认方法调用其他接口(interface)方法(你得到一个委托(delegate)乒乓)。 JLS 对这个问题出奇地沉默......

这里是一个小代码示例:

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。此代码复制自 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动态代理和默认方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26206614/

相关文章:

java - 如何修复 Kuali 启动错误无法解析占位符 'datasource.url'?

java - 如何从 Java 项目运行 Docker 容器?

java-8 - 默认 ForkJoinPool 执行器花费很长时间

java调用带有动态数量参数的dnamall方法

java - Hibernate 可以用作 Google App Engine 中的 JPA 提供者吗

java - 如何在android中获取完整日期?

Java 8 功能接口(interface)歧义引用(这是一个错误吗?)

java - 打印出过滤流对象的一些字段

Java 8 Streams 并尝试使用资源

java - 过滤集合的元素