如何使用AOP拦截参数中的super方法调用?

时间:2010-04-15 15:09:27

标签: java aop

我正在扩展一个类并重写一个方法。我想做的就是调用super,但是调用一个被修改的参数,在其中一个方法被调用。一个例子使它更清楚:

// Foo is an interface and also this method is part of an interface
@Override
public void foo(Foo foo) {
    // I want to intercept the call to foo.bar() in super
    super.foo(foo);
}

我宁愿使用不需要自己编译器的工具。什么是最佳的?

1 个答案:

答案 0 :(得分:3)

鉴于Foo是一个界面,您可以考虑使用dynamic proxy

  1. 包裹原始foo
  2. 拦截所有邮件并将其转发给原始邮件
  3. 上述链接中有完整的example。这只是一个想法:

    public class DebugProxy implements java.lang.reflect.InvocationHandler {
    
       private Object obj;
    
       private DebugProxy(Object obj) {
          this.obj = obj;
       }
    
       public Object invoke(Object proxy, Method m, Object[] args) throws Throwable
       {
           System.out.println("before method " + m.getName());
           return m.invoke(obj, args); 
       }
    }
    
    Foo original = ... ;
    Foo wrapper = (Foo) java.lang.reflect.Proxy.newProxyInstance(
        original.getClass().getClassLoader(),
        original.getClass().getInterfaces(),
        new DebugProxy(original));
    wrapper.bar(...);
    

    请注意,如果Foo不是接口,您仍然可以继承Foo并手动覆盖所有方法以转发它们。

    class SubFoo extends Foo
    {
        Foo target;
    
        SubFoo( Foo target ) { this.target = target };
    
        public void method1() { target.method1(); }
    
        ...
    }
    

    这是伪代码,我还没有测试过。在这两种情况下,包装器都允许您拦截super中的呼叫。

    当然,包装器与原始Foo的类不同,所以如果超级使用

    1. 反射
    2. instanceof
    3. 或直接访问实例变量(不通过getter / setter)
    4. ,那可能会有问题。

      希望我理解你的问题并且有所帮助。