如何创建代理并调用默认接口方法,就好像它们是由代理超类实现的一样?例如:
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
的代理,在调用Super::returnSomething
时将使用Bar::returnSomethingMore
实现。
我试过了:
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);
// -> StackOverflowError
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
方法返回2
?
答案 0 :(得分:0)
我放弃了cglib
(感谢SO&#39;标记我已经知道它不再处于积极开发状态)并采用了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);
}