在代理上调用接口默认方法
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);
}
如何创建代理并调用默认接口方法,就好像它们是由代理超级 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);
}