代码之家  ›  专栏  ›  技术社区  ›  hleinone

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

  •  2
  • hleinone  · 技术社区  · 16 年前

    我正在扩展一个类并重写一个方法。我要做的只是调用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 回复  |  直到 16 年前
        1
  •  3
  •   ewernli    16 年前

    鉴于 Foo 是一个接口,您可以考虑使用 dynamic proxy 那将:

    1. 把原来的foo包起来
    2. 拦截所有消息并将其转发到原始foo

    有一个完整的 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(...);
    

    注意如果 福 不是一个接口,您仍然可以子类 福 并手动重写所有方法以转发它们。

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

    这是伪代码,我还没有测试过。在这两种情况下,包装器都允许拦截调用 super .

    当然,包装器与原来的类不同 福 ,所以如果超级用户

    1. 反射
    2. instanceof
    3. 或者直接访问实例变量(不通过getter/setter)

    ,那么它可能有问题。

    希望我能正确理解你的问题,并且能帮上忙。