在代理上调用接口默认方法

Invoke an interface default method on a proxy

如何创建代理并调用默认接口方法,就好像它们是由代理超级 class 实现的一样?例如:

interface Foo {

    default int returnSomething() {
        return 1;
    }

}

interface Bar extends Foo {

    default int returnSomethingMore() {
        return returnSomething();
    }

}

class Super implements Foo {

    @Override
    public int returnSomething() {
        return 2;
    }

}

我需要 Bar 的代理,它会在调用 Bar::returnSomethingMore 时使用 Super::returnSomething 实现。

我试过这个:

Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(Super.class);
enhancer.setInterfaces(new Class[] { Bar.class });
enhancer.setCallback((obj, method, args, proxy) -> {
    if (method.getName().equals("returnSomethingMore")) {

        return proxy.invokeSuper(obj, args);
        // -> NoSuchMethodError

        return proxy.invoke(obj, args);
        // -> WhosebugError

        Class<?> declaringClass = method.getDeclaringClass();
        Lookup lookup = MethodHandles.lookup();
        return MethodHandles
                .privateLookupIn(declaringClass, lookup)
                .unreflectSpecial(method, declaringClass)
                .bindTo(obj)
                .invokeWithArguments(args);
        // -> returns 1, not 2
    }
});

如何创建其 returnSomethingMore 方法 returns 2 的代理对象?

我放弃了 cglib(多亏了 SO 的标签,我知道它不再处于积极开发中)并采用了 ByteBuddy,它为我提供了我需要的代理:

@Test
public void defaultInterfaceMethodTest() {
    Class<? extends Super> loaded = new ByteBuddy()
            .subclass(Super.class)
            .implement(Bar.class).make()
            .load(this.getClass().getClassLoader()).getLoaded();
    Bar newInstance = (Bar) loaded.getConstructor().newInstance();
    int shouldBeTwo = newInstance.returnSomethingMore();
    Assert.assertEquals(2, shouldBeTwo);
}