When writing a MethodInterceptor the state of the MethodInvocation passed in by
Guice is only valid before and after proceed has been called. And before the
invoke method returns.
i.e.
@Override public Object invoke(final MethodInvocation invocation) throws
Throwable {
// invocation valid
Object result = invocation.proceed(); // invocation changes for the duration of the proceed call
// invocation valid
return result;
// invocation changes due to return
}
The reason for this is the use of the mutable "index" field in the
InterceptedMethodInvocation class.
The implementation of "proceed()" recursively passes itself to each of the
interceptors. Effectively "index" is working as a stack pointer.
The consequence of this is that I cannot keep a reference to the
MethodInvocation object and use it somewhere else. For example, I want to write
an method interceptor that executes the intercepted method in a different
thread. An immutable implementation of MethodInvocation would be preferable.
For example copying the InterceptedMethodInvocation before each invocation
would solve this problem by making the MethodInvocation more like an immutable
object. Like this:
private class InterceptedMethodInvocation implements MethodInvocation {
final Object proxy;
final Object[] arguments;
final MethodProxy methodProxy;
public InterceptedMethodInvocation(final Object proxy, final MethodProxy methodProxy,
final Object[] arguments) {
this(proxy, methodProxy, arguments, -1);
}
public InterceptedMethodInvocation(final Object proxy, final MethodProxy methodProxy,
final Object[] arguments, int index) {
this.proxy = proxy;
this.methodProxy = methodProxy;
this.arguments = arguments;
this.index = index;
}
public Object proceed() throws Throwable {
try {
int nextIndex = index + 1;
return nextIndex == interceptors.length
? methodProxy.invokeSuper(proxy, arguments)
: interceptors[nextIndex].invoke(new InterceptedMethodInvocation(proxy, methodProxy, arguments, nextIndex));
} catch (final Throwable t) {
pruneStacktrace(t);
throw t;
}
}
public Method getMethod() {
return method;
}
public Object[] getArguments() {
return arguments;
}
public Object getThis() {
return proxy;
}
public AccessibleObject getStaticPart() {
return getMethod();
}
}
Original issue reported on code.google.com by flamingp...@gmail.com on 12 Feb 2012 at 6:32
Original issue reported on code.google.com by
flamingp...@gmail.com
on 12 Feb 2012 at 6:32