Java 在代理上调用接口默认方法
如何创建代理并调用默认接口方法,就好像它们是由代理超类实现的一样?例如:Java 在代理上调用接口默认方法,java,cglib,dynamic-proxy,Java,Cglib,Dynamic Proxy,如何创建代理并调用默认接口方法,就好像它们是由代理超类实现的一样?例如: interface Foo { default int returnSomething() { return 1; } } interface Bar extends Foo { default int returnSomethingMore() { return returnSomething(); } } class Super impleme
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);
// -> 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
}
});
Enhancer Enhancer=new Enhancer();
增强器.setSuperclass(Super.class);
setInterfaces(新类[]{Bar.Class});
setCallback((对象、方法、参数、代理)->{
if(method.getName().equals(“returnSomethingMore”)){
返回proxy.invokeSuper(obj,args);
//->NoSuchMethodError
返回proxy.invoke(obj,args);
//->堆栈溢出错误
Class declaringClass=方法.getDeclaringClass();
Lookup Lookup=MethodHandles.Lookup();
返回方法句柄
.privateLookupIn(去极化类,查找)
.无反射特殊(方法,去极化等级)
.bindTo(obj)
.调用参数(args);
//->返回1,而不是2
}
});
我如何创建一个代理对象,它的
returnSomethingMore
方法返回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);
}
@测试
public void defaultInterfaceMethodTest(){
基本上,我需要的是避免某些方法的代理,即让代理实例自己调用默认实现我在Enhancer
上看到的是callbackFilter
,它允许您选择要使用哪个回调,而不是完全避免使用一个。还尝试了该方法的NoOp
回调过滤器,然后它仍然返回1
,而不是2
(例如,它不使用returnSomething
的Super
实现)。