Wie kann eine Standardmethode von einem dynamischen Proxy explizit aufgerufen werden?

Since Java 8-Schnittstellen können Standardmethoden haben. Ich weiß, wie man die Methode explizit von der Implementierungsmethode aus aufruft, d. Explizit eine Standardmethode in Java aufrufen)

Aber wie kann ichausdrücklic Standardmethode mit Reflektion aufrufen, zum Beispiel auf einem Proxy?

Beispiel

interface ExampleMixin {

  String getText();

  default void printInfo(){
    System.out.println(getText());
  }
}

class Example {

  public static void main(String... args) throws Exception {

    Object target = new Object();

    Map<String, BiFunction<Object, Object[], Object>> behavior = new HashMap<>();

    ExampleMixin dynamic =
            (ExampleMixin) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),new Class[]{ExampleMixin.class}, (Object proxy, Method method, Object[] arguments) -> {

                //custom mixin behavior
                if(behavior.containsKey(method.getName())) {
                    return behavior.get(method.getName()).apply(target, arguments);
                //default mixin behavior
                } else if (method.isDefault()) {
                    //this block throws java.lang.IllegalAccessException: no private access for invokespecial
                    return MethodHandles.lookup()
                                        .in(method.getDeclaringClass())
                                        .unreflectSpecial(method, method.getDeclaringClass())
                                        .bindTo(target)
                                        .invokeWithArguments();
                //no mixin behavior
                } else if (ExampleMixin.class == method.getDeclaringClass()) {
                    throw new UnsupportedOperationException(method.getName() + " is not supported");
                //base class behavior
                } else{
                    return method.invoke(target, arguments);
                }
            });

    //define behavior for abstract method getText()
    behavior.put("getText", (o, a) -> o.toString() + " myText");

    System.out.println(dynamic.getClass());
    System.out.println(dynamic.toString());
    System.out.println(dynamic.getText());

    //print info should by default implementation
    dynamic.printInfo();
  }
}

Bearbeiten Ich weiß, dass eine ähnliche Frage in @ gestellt wurWie rufe ich Java 8-Standardmethoden refletiv auf?, aber dies hat mein Problem aus zwei Gründen nicht gelöst:

das in dieser Frage beschriebene Problem bezog sich darauf, wie es über Reflection aufgerufen werden kannallgemei - es wurde also keine Unterscheidung zwischen Standardmethode und Überschreibungsmethode getroffen - und dies ist einfach, Sie benötigen nur eine Instanz. Eine der Antworten - unter Verwendung von Methodenhandles - funktioniert nur mit unangenehmen Hack (imho) wie dem Ändern von Zugriffsmodifikatoren in Felder der Lookup-Klasse. Dies ist dieselbe Kategorie von "Lösungen" wie diese:Ändern Sie das private statische Endfeld mithilfe von Java Reflection: es ist gut zu wissen, dass es möglich ist, aber ich würde es nicht in der Produktion verwenden - Ich suche einen "offiziellen" Weg, um es zu tun.

DasIllegalAccessException wird in @ geworfunreflectSpecial

Caused by: java.lang.IllegalAccessException: no private access for invokespecial: interface example.ExampleMixin, from example.ExampleMixin/package
at java.lang.invoke.MemberName.makeAccessException(MemberName.java:852)
at java.lang.invoke.MethodHandles$Lookup.checkSpecialCaller(MethodHandles.java:1568)
at java.lang.invoke.MethodHandles$Lookup.unreflectSpecial(MethodHandles.java:1227)
at example.Example.lambda$main$0(Example.java:30)
at example.Example$Lambda$1/1342443276.invoke(Unknown Source)

Antworten auf die Frage(8)

Ihre Antwort auf die Frage