xiaodududu / google-guice

Automatically exported from code.google.com/p/google-guice
Apache License 2.0
0 stars 0 forks source link

Possibility to save state of InterceptorStackCallback in MethodInvocation implementation #684

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
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