为具有默认方法的接口(interface)提供动态代理,我该如何调用默认方法?通过使用类似 defaultmethod.invoke(this, ...)
的方法,您只需调用代理调用处理程序(这在某种程度上是正确的,因为您没有此接口(interface)的实现类)。
我有一个解决方法,使用 ASM 创建一个实现接口(interface)的类,并将此类调用委托(delegate)给此类的一个实例。但这不是一个好的解决方案,特别是如果默认方法调用其他接口(interface)方法(你得到一个委托(delegate)乒乓)。 JLS 对这个问题出奇地沉默......
这里是一个小代码示例:
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。此代码复制自 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动态代理和默认方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26206614/