我想用这个类来抓住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);
}
为什么呢?感谢。
答案 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新手,我只是将其作为任何其他人绊倒这个问题的参考。