AspectJ - Можно ли поймать исполнение совета?

У меня есть CachingAspect который выполняет некоторое простое кэширование на правильно аннотированных методах, используя around совет. Теперь я хочу проследить кэширование и around совет в частности.

Пока что я могу перехватывать вызовы методов внутри around совет, но не сам совет. В конечном счете, я хотел бы получить подпись метода around совет советует. Является ли это возможным?

Заранее спасибо!

3 ответа

Решение

Что вы подразумеваете под

у меня не работает [adviceexecution pointcut]

Для меня это работает просто отлично, вот так:

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)

Увидеть adviceexecution() pointcut.

Вы можете использовать thisJoinPoint.getSignature() внутри совета, чтобы получить сигнатуру метода следующим образом:

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

    Log.d(ATAG, "=========== entering " + method+", parms="+Arrays.toString(thisJoinPoint.getArgs()));
}
Другие вопросы по тегам