Java8 dynamic proxy and default methods

后端 未结 4 1249
北荒
北荒 2021-01-01 20:43

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

4条回答
  •  臣服心动
    2021-01-01 21:08

    The accepted answer uses setAccessible(true) to break into MethodHandles.Lookup, something that is restricted in Java 9 and beyond. This mail describes a JDK change that works for Java 9 or later.

    It is possible to get this to work on Java 8 (and later) if you can get the writer of the interface to call your utility with an instance of MethodHandles.Lookup created in the interface (so it gets the permission to access the default methods of the interface):

    interface HelloGenerator {
      public static HelloGenerator  createProxy() {
        // create MethodHandles.Lookup here to get access to the default methods
        return Utils.createProxy(MethodHandles.lookup(), HelloGenerator.class);
      }
      abstract String name();
      default void sayHello() {
        System.out.println("Hello " + name());
      }
    }
    
    public class Utils {
      static 

    P createProxy(MethodHandles.Lookup lookup, Class

    type) { InvocationHandler handler = (proxy, method, args) -> { if (method.isDefault()) { // can use unreflectSpecial here, but only because MethodHandles.Lookup // instance was created in the interface and passed through return lookup .unreflectSpecial(method, method.getDeclaringClass()) .bindTo(proxy) .invokeWithArguments(args); } return ...; // your desired proxy behaviour }; Object proxy = Proxy.newProxyInstance( type.getClassLoader(), new Class[] {type}, handler); return type.cast(proxy); } }

    This approach won't handle all Java 8 use cases, but it did handle mine.

提交回复
热议问题