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)
Вы можете использовать thisJoinPoint.getSignature() внутри совета, чтобы получить сигнатуру метода следующим образом:
pointcut tolog1() : execution(* Activity+.*(..)) ;
before() : tolog1() {
String method = thisJoinPoint.getSignature().toShortString();
Log.d(ATAG, "=========== entering " + method+", parms="+Arrays.toString(thisJoinPoint.getArgs()));
}