如何横切注释的方法和构造函数?

这就是我正在做的事情:

@Aspect public class MethodLogger { @Around("(execution(* *(..)) || initialization(*.new(..))) && @annotation(Foo)") public Object wrap(ProceedingJoinPoint point) throws Throwable { // works fine, but only for methods } } 

该代码段工作正常,但仅适用于方法调用。 这是AspectJ maven插件在应用方面后所说的(不是在编译期间,它工作得很好):

 around on initialization not supported (compiler limitation) 

任何解决方法? 我在使用OpenJDK 7:

 java version "1.7.0_05" Java(TM) SE Runtime Environment (build 1.7.0_05-b06) Java HotSpot(TM) 64-Bit Server VM (build 23.1-b03, mixed mode) 

由于技术限制,没有关于initialization()preinitialization()切入点的around()建议。 并且在输入和退出相应的连接点时的时间顺序存在另一个问题。 看看这个例子:

 public abstract class ApplicationBase { private int id = 0; public ApplicationBase(int id) { this.id = id; } } 
 public class Application extends ApplicationBase { private String name = ""; public Application(int id, String name) { super(id); this.name = name; } public static void main(String[] args) { new Application(1, "Foo"); new Application(2, "Bar"); } } 
 public aspect ExecutionTimingAspect { private String indentText = ""; pointcut constructorCall() : call(*Application*.new(..)); pointcut constructorRelated() : constructorCall() || initialization(*Application*.new(..)) || preinitialization(*Application*.new(..)) || execution(*Application*.new(..)); after() : constructorRelated() { indentText = indentText.substring(2); System.out.println(indentText + "<< " + thisJoinPointStaticPart); } before() : constructorRelated() { System.out.println(indentText + ">> " + thisJoinPointStaticPart); indentText += " "; } Object around() : constructorCall() { long startTime = System.nanoTime(); Object result = proceed(); System.out.println(indentText + "Constructor runtime = " + (System.nanoTime() - startTime) / 1.0e9 + " s\n"); return result; } } 

您将看到以下输出:

 >> call(Application(int, String)) >> preinitialization(Application(int, String)) << preinitialization(Application(int, String)) >> preinitialization(ApplicationBase(int)) << preinitialization(ApplicationBase(int)) >> initialization(ApplicationBase(int)) >> execution(ApplicationBase(int)) << execution(ApplicationBase(int)) << initialization(ApplicationBase(int)) >> initialization(Application(int, String)) >> execution(Application(int, String)) << execution(Application(int, String)) << initialization(Application(int, String)) << call(Application(int, String)) Constructor runtime = 0.00123172 s >> call(Application(int, String)) >> preinitialization(Application(int, String)) << preinitialization(Application(int, String)) >> preinitialization(ApplicationBase(int)) << preinitialization(ApplicationBase(int)) >> initialization(ApplicationBase(int)) >> execution(ApplicationBase(int)) << execution(ApplicationBase(int)) << initialization(ApplicationBase(int)) >> initialization(Application(int, String)) >> execution(Application(int, String)) << execution(Application(int, String)) << initialization(Application(int, String)) << call(Application(int, String)) Constructor runtime = 0.00103393 s 

你能看到派生类的预初始化是如何在其基类的预初始化之前开始和结束的吗? 初始化是如何工作的另一种方式,但作为一个额外的复杂构造函数执行嵌入初始化?

也许现在你明白只测量初始化,即使通过around()可能,也不会反映构造函数的总体执行时间。 因此,如果你足够幸运能够拦截构造函数call()而不是execution()因为你可以访问调用代码,你可以使用around()就像我在我的例子中所做的那样(也就是说,方式,不是线程安全的,但我试着保持简单)。 如果你不能影响调用者,但只能编织被调用者,你需要使用其他技巧,例如在通过before()输入某个构造函数的预初始化时的方面内部簿记,然后在初始化相同的构造函数调用时after()退出。 即你需要在建议执行之间保持一些内部状态。 这是可能的,但有点复杂。 如果您想进一步讨论,请告诉我。

作为解决方法 – 您可以引入工厂以满足这些需求,以应用其方法的建议。