С моим ограниченным представлением об АОП, я считаю, что мы можем сделать что-то до и после метода JoinPoint, т.е. в этом случае, но как мы можем обернуть реализацию, как указано выше?
Есть ли у васВы когда-нибудь читали очень хорошее руководство Spring AOP ?Одним из первых вещей, которые вы заметите, будет объяснение типов советов и то, что есть не только до и после, но также вокруг совета .Это то, что вы хотите использовать.
Вот как это работает:
Вспомогательные классы Java:
package de.scrum_master.app;
public class SomeType {}
package de.scrum_master.app;
public class SomeResource implements AutoCloseable {
@Override public void close() throws Exception {}
}
Интерфейсы:
package de.scrum_master.app;
public interface X {
void methodX1();
int methodX2(String s);
}
package de.scrum_master.app;
public interface Y {
void methodY1();
String methodY2(int i);
void methodY3(SomeType s);
}
Реализация интерфейса + приложение драйвера:
Я реализовал пример в AspectJ, а не в Spring AOP.Таким образом, вы не видите контекста приложения, но знаете, как это сделать, не так ли?
package de.scrum_master.app;
import org.springframework.stereotype.Component;
@Component
public class MyImpl implements X, Y {
@Override public void methodY1() { System.out.println("Y1"); methodX2("bar"); }
@Override public String methodY2(int i) { System.out.println("Y2"); return "dummy"; }
@Override public void methodY3(SomeType s) { System.out.println("Y3"); }
@Override public void methodX1() { System.out.println("X1"); methodY1(); }
@Override public int methodX2(String s) { System.out.println("X2"); return 42; }
public static void main(String[] args) {
MyImpl myImpl = new MyImpl();
myImpl.methodX1();
myImpl.methodX2("foo");
myImpl.methodY1();
myImpl.methodY2(11);
myImpl.methodY3(new SomeType());
}
}
Обратите внимание, что и methodX1()
, и methodY1()
вызывают методы внутри.Это будет важно с точки зрения различия между Spring AOP и AspectJ позже.
Aspect:
В Spring AOP вы можете пропустить часть execution(* *(..)) &&
, я простоиспользуйте его здесь, чтобы избежать перехвата других точек соединения, таких как call()
и вздутие журнала.Поскольку Spring AOP не знает ничего другого, кроме execution()
, в этом нет необходимости.Скобки вокруг блока ... || ...
pointcut также могут исчезнуть.
package de.scrum_master.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import de.scrum_master.app.SomeResource;
@Component
@Aspect
public class WrapMethodsAspect {
@Around("execution(* *(..)) && (within(de.scrum_master.app.X+) || within(de.scrum_master.app.Y+))")
public Object wrapperAdvice(ProceedingJoinPoint thisJoinPoint) throws Throwable {
System.out.println("Wrapping " + thisJoinPoint);
try (SomeResource res = new SomeResource()) {
return thisJoinPoint.proceed();
}
finally {
System.out.println("Unwrapping " + thisJoinPoint);
}
}
}
Вывод на консоль с AspectJ:
Wrapping execution(void de.scrum_master.app.MyImpl.main(String[]))
Wrapping execution(void de.scrum_master.app.MyImpl.methodX1())
X1
Wrapping execution(void de.scrum_master.app.MyImpl.methodY1())
Y1
Wrapping execution(int de.scrum_master.app.MyImpl.methodX2(String))
X2
Unwrapping execution(int de.scrum_master.app.MyImpl.methodX2(String))
Unwrapping execution(void de.scrum_master.app.MyImpl.methodY1())
Unwrapping execution(void de.scrum_master.app.MyImpl.methodX1())
Wrapping execution(int de.scrum_master.app.MyImpl.methodX2(String))
X2
Unwrapping execution(int de.scrum_master.app.MyImpl.methodX2(String))
Wrapping execution(void de.scrum_master.app.MyImpl.methodY1())
Y1
Wrapping execution(int de.scrum_master.app.MyImpl.methodX2(String))
X2
Unwrapping execution(int de.scrum_master.app.MyImpl.methodX2(String))
Unwrapping execution(void de.scrum_master.app.MyImpl.methodY1())
Wrapping execution(String de.scrum_master.app.MyImpl.methodY2(int))
Y2
Unwrapping execution(String de.scrum_master.app.MyImpl.methodY2(int))
Wrapping execution(void de.scrum_master.app.MyImpl.methodY3(SomeType))
Y3
Unwrapping execution(void de.scrum_master.app.MyImpl.methodY3(SomeType))
Unwrapping execution(void de.scrum_master.app.MyImpl.main(String[]))
Здесь вы заметили две вещи:
- Выполнение статического метода
main(..)
регистрируется.Это не произойдет с Spring AOP. - Внутренние вызовы методов регистрируются.Этого также не произойдет с Spring AOP.
Вывод на консоль с Spring AOP:
Wrapping execution(void de.scrum_master.app.MyImpl.methodX1())
X1
Unwrapping execution(void de.scrum_master.app.MyImpl.methodX1())
Wrapping execution(int de.scrum_master.app.MyImpl.methodX2(String))
X2
Unwrapping execution(int de.scrum_master.app.MyImpl.methodX2(String))
Wrapping execution(void de.scrum_master.app.MyImpl.methodY1())
Y1
Unwrapping execution(void de.scrum_master.app.MyImpl.methodY1())
Wrapping execution(String de.scrum_master.app.MyImpl.methodY2(int))
Y2
Unwrapping execution(String de.scrum_master.app.MyImpl.methodY2(int))
Wrapping execution(void de.scrum_master.app.MyImpl.methodY3(SomeType))
Y3
Unwrapping execution(void de.scrum_master.app.MyImpl.methodY3(SomeType))
В большинстве случаев Spring AOP достаточно для пользователей Spring,Но если вам нужен более мощный подход для захвата других типов pointcut или, например, внутренних вызовов вложенных методов, вы должны использовать AspectJ через ткачество времени загрузки (LTW) .