1

我有一个CachingAspect使用建议对正确注释的方法执行一些简单缓存的方法around。现在,我想做的是around特别跟踪缓存和建议。

到目前为止,我能够拦截around建议中的方法调用,但不能拦截建议本身。最终,我想获得around建议所建议方法的签名。可能吗?

提前致谢!

4

3 回答 3

1

adviceexecution()切入点

于 2011-05-18T10:13:00.187 回答
1

你是什​​么意思

[建议执行切入点] 对我不起作用

对我来说它工作得很好,就像这样:

public aspect MetaAspect {
    before() : within(DummyAspect) && adviceexecution() {
        System.out.println("MetaAspect: " + thisJoinPointStaticPart.getSignature());
        for (Object arg : thisJoinPoint.getArgs())
            System.out.println("    " + arg);
    }
}

从那时起,查看打印的签名,您应该能够进一步细化从 DummyAspect 中选择的建议,如果有多个并且它们具有不同的签名。


更新:

好的,您已经编辑了您的问题,并指出您需要确定的不仅仅是adviceexecution()拦截方法的签名。对此没有 100% 的解决方案,但如果您确保拦截的建议以某种方式引用 的方法thisJoinPointStaticPart,则会将 的实例JoinPoint.StaticPart添加到建议自己的签名中,并且可以从您的元方面访问。这是一个完整的代码示例:

驱动应用:

package de.scrum_master.app;

public class Application {
    public static void main(String[] args) {
        Application application = new Application();
        application.writeProperty("fullName", "John Doe");
        application.readProperty("firstName");
        application.doSomething(11);
    }

    public void writeProperty(String name, String value) {}
    public String readProperty(String name) { return "foo"; }
    public void doSomething(int number) {}
}

缓存方面:

package de.scrum_master.aspect;

public aspect CachingAspect {
    pointcut readMethods(String propertyName) :
        execution(* *.read*(String)) && args(propertyName);

    before(String propertyName) : readMethods(propertyName) {
        System.out.println(
            "[CachingAspect] Read method called for property '" + propertyName + "'"
        );
    }

    Object around(String propertyName) : readMethods(propertyName) {
        System.out.println(
            "[CachingAspect] Caching property '" + propertyName +
            "' in method " + thisJoinPointStaticPart.getSignature()
        );
        return proceed(propertyName);
    }
}

如您所见,在这方面有两个建议。第一个不访问任何加入点成员,第二个可以。即我们将能够仅在我们的元方面找出第二个的目标签名。

元方面:

package de.scrum_master.aspect;

import org.aspectj.lang.JoinPoint.StaticPart;

public aspect AdviceInterceptor {
    before() : within(CachingAspect) && adviceexecution() {
        System.out.println("[AdviceInterceptor] Intercepting " + thisJoinPointStaticPart);
        boolean foundSignature = false;
        for (Object arg : thisJoinPoint.getArgs()) {
            if (arg instanceof StaticPart) {
                foundSignature = true;
                StaticPart jpStaticPart = (StaticPart) arg;
                System.out.println("[AdviceInterceptor] Target method = " + jpStaticPart.getSignature());
                break;
            }
        }
        if (!foundSignature)
            System.out.println("[AdviceInterceptor] Target method cannot be determined from advice signature");
    }
}

元通知迭代其参数以找到JoinPoint.StaticPart类型参数。如果找到,则打印其目标签名,否则在循环后打印失败说明。

样本输出:

[AdviceInterceptor] Intercepting adviceexecution(void de.scrum_master.aspect.CachingAspect.before(String))
[AdviceInterceptor] Target method cannot be determined from advice signature
[CachingAspect] Read method called for property 'firstName'
[AdviceInterceptor] Intercepting adviceexecution(Object de.scrum_master.aspect.CachingAspect.around(String, AroundClosure, JoinPoint.StaticPart))
[AdviceInterceptor] Target method = String de.scrum_master.app.Application.readProperty(String)
[CachingAspect] Caching property 'firstName' in method String de.scrum_master.app.Application.readProperty(String)
于 2012-08-09T16:21:53.263 回答
1

您可以在建议中使用 thisJoinPoint.getSignature() 来获取方法签名,如下所示:

pointcut tolog1() : execution(* Activity+.*(..)) ;
before() : tolog1() {
    String method = thisJoinPoint.getSignature().toShortString();

    Log.d(ATAG, "=========== entering " + method+", parms="+Arrays.toString(thisJoinPoint.getArgs()));
}
于 2011-05-19T13:23:32.620 回答