【问题标题】:How to use AOP to intercept a method call in super on an argument?如何使用 AOP 拦截参数上的超级方法调用?
【发布时间】:2010-04-15 15:09:27
【问题描述】:

我正在扩展一个类并覆盖一个方法。我想要做的就是调用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);
}

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

【问题讨论】:

    标签: java aop


    【解决方案1】:

    鉴于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(...);
    

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

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

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

    当然,包装器和原来Foo的类不一样,所以如果super使用了

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

    ,那么可能有问题。

    希望我能正确理解您的问题并且对您有所帮助。

    【讨论】:

    • 就是这样。我在想办法太难了。谢谢你把我带回地面。
    猜你喜欢
    • 1970-01-01
    • 2013-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-04
    • 1970-01-01
    相关资源
    最近更新 更多