AspectJ,无法拦截super()构造函数调用

时间:2014-05-16 14:11:40

标签: aspectj

我想用这个类来抓住java.io.FileInputStream的子类的super()

package de.scrum_master.app;

class ABC {
    public ABC() {
        System.out.println("Ctr ABC");
    }
}

public class DEF extends ABC {
    public DEF() throws Exception {
       System.out.println("Ctr DEF");
    }

    static class MyFileInputStream extends java.io.FileInputStream {
        MyFileInputStream() throws Exception {
            super("de/scrum_master/app/ABC.java"); // HERE
        }
    };

    public static void main(String[] args) throws Exception {
        new MyFileInputStream();
        new DEF();
    }
}

我可以像这样抓住DEF和ABC之间的初始化:

@Before("initialization(de.scrum_master.app.DEF.new(..))")
public void test(JoinPoint thisJoinPoint) throws AuditReactiveException {
    System.err.println("Aspect DEF:"+thisJoinPoint);
}

但不是java.io.FileInputStream

 @Before("initialization(java.io.FileInputStream.new(..))")
    public void test2(JoinPoint thisJoinPoint) throws Exception {
        System.err.println("Aspect FileInpputStream:"+thisJoinPoint);
    }

为什么呢?感谢。

1 个答案:

答案 0 :(得分:3)

简单的问题,简单的回答:因为FileInputStream不是您自己的代码库的一部分,而是JDK / JRE的一部分。 JDK超出了AspectJ的影响,因为它的类是运行时的一部分,您的应用程序及其方面在其中执行。您可以捕获对JDK类的调用,但不捕获执行。

也许你更幸运了
call(java.io.FileInputStream.new(..))

P.S。:你也可以通过创建一个方面丰富的版本来将方面编织到JRE类中。 rt.jar ,但这不是推荐也不是微不足道的。我已经做到了,只是为了看它是否有效。但是,采用这些措施通常是不良方面设计的症状,而不是解决实际问题的方法。

更新:好吧,我忘记了call()切入点的语义。 AspectJ documentation说:

  

方法调用:调用方法时,不包括非静态方法的超级调用。

实际上,如果不创建编织的JDK / JRE,则无法捕获super()对JDK / JRE构造函数的调用或初始化。如果在建议中使用call()preinitialization()切入点,至少可以确保在超级构造函数中发生可能的异常之前发生日志记录 - 在调用超级构造函数之后发生initialization()

更新2 :如果您想了解无法解决此问题的技术细节,请参阅this discussion。注意,这实际上不适用于AspectJ新手,我只是将其作为任何其他人绊倒这个问题的参考。