Java8动态代理和默认方法 [英] Java8 dynamic proxy and default methods
问题描述
拥有使用默认方法的接口的动态代理,如何调用默认方法?通过使用像 defaultmethod.invoke(this,...)
之类的东西,你只需要调用你的代理调用处理程序(这在某种程度上是正确的,因为你没有这个接口的实现类)。
Having a dynamic proxy for an interface with default methods, how do I invoke a default method? By using something like defaultmethod.invoke(this, ...)
you just get your proxy invocation handler called (Which is somehow correct, cause you have no implementing class for this interface).
我有一个解决方法,使用ASM创建一个实现接口的类,并将这些调用委托给这个类的实例。但这不是一个好的解决方案,特别是如果默认方法调用其他接口方法(你得到一个委托人ping-pong)。对于这个问题,JLS出乎意料地保持沉默...
I have a workaround using ASM to create a class implementing the interface and delegating such calls to an instance of this class. But this is not a good solution, especially if the default method calls other interface methods (you get a delegator ping-pong). The JLS is surprisingly silent about this question...
这里有一个小代码示例:
Here a small code example:
public class Java8Proxy implements InvocationHandler {
public interface WithDefaultMethod {
void someMethod();
default void someDefaultMethod() {
System.out.println("default method invoked!");
}
}
@Test
public void invokeTest() {
WithDefaultMethod proxy = (WithDefaultMethod) Proxy.newProxyInstance(
WithDefaultMethod.class.getClassLoader(),
new Class<?>[] { WithDefaultMethod.class }, this);
proxy.someDefaultMethod();
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// assuming not knowing the interface before runtime (I wouldn't use a
// proxy, would I?)
// what to do here to get the line printed out?
// This is just a loop
// method.invoke(this, args);
return null;
}
}
推荐答案
你可以使用 MethodHandles 类型你的 InvocationHandler 。此代码复制自零周转。
You can use the MethodHandles type in your InvocationHandler. This code is copied from Zero Turnaround.
Constructor<MethodHandles.Lookup> constructor;
Class<?> declaringClass;
Object result;
if (method.isDefault()) {
declaringClass = method.getDeclaringClass();
constructor = MethodHandles.Lookup.class.getDeclaredConstructor(Class.class, int.class);
constructor.setAccessible(true);
result = constructor.
newInstance(declaringClass, MethodHandles.Lookup.PRIVATE).
unreflectSpecial(method, declaringClass).
bindTo(proxy).
invokeWithArguments(args);
return(result);
}
这篇关于Java8动态代理和默认方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!