文章目录
配置类
@Component
@Aspect
public class LogComponent {
@Pointcut("execution(* com.test.UserService.*(..))")
public void plc() {
}
@Before("plc()")
public void before(JoinPoint jp) {
String name = jp.getSignature().getName();
System.out.println("beforeLog:" + name);
}
@After("plc()")
public void after(JoinPoint jp) {
String name = jp.getSignature().getName();
System.out.println("afterLog:" + name);
}
@AfterReturning(value = "plc()", returning = "result")
public void returning(JoinPoint jp, Object result) {
String name = jp.getSignature().getName();
System.out.println("returningLog:" + name);
System.out.println("returningLog:" + result);
}
@AfterThrowing(value = "plc()", throwing = "e")
public void throwing(JoinPoint jp, Exception e) {
String name = jp.getSignature().getName();
System.out.println("throwingLog:" + name);
System.out.println("throwingLog:" + e.getMessage());
}
@Around("plc()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
Object proceed = pjp.proceed();
String name = pjp.getSignature().getName();
System.out.println("aroundLog:" + name);
return proceed;
}
}
@Component
@Aspect
public class TransactionComponent {
@Pointcut("execution(* com.test.UserService.*(..))")
public void plc() {
}
@Before("plc()")
public void before(JoinPoint jp) {
String name = jp.getSignature().getName();
System.out.println("beforeTransaction:" + name);
}
@After("plc()")
public void after(JoinPoint jp) {
String name = jp.getSignature().getName();
System.out.println("afterTransaction:" + name);
}
@AfterReturning(value = "plc()", returning = "result")
public void returning(JoinPoint jp, Object result) {
String name = jp.getSignature().getName();
System.out.println("returningTransaction:" + name);
System.out.println("returningTransaction:" + result);
}
@AfterThrowing(value = "plc()", throwing = "e")
public void throwing(JoinPoint jp, Exception e) {
String name = jp.getSignature().getName();
System.out.println("throwingTransaction:" + name);
System.out.println("throwingTransaction:" + e.getMessage());
}
@Around("plc()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
Object proceed = pjp.proceed();
String name = pjp.getSignature().getName();
System.out.println("aroundTransaction:" + name);
return proceed;
}
}
通知的初始化
对每个@Aspect切面类作处理
public List<Advisor> buildAspectJAdvisors() {
List<String> aspectNames = this.aspectBeanNames;
...
for (String beanName : beanNames) {
...
MetadataAwareAspectInstanceFactory factory =
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
if (this.beanFactory.isSingleton(beanName)) {
this.advisorsCache.put(beanName, classAdvisors);
}
else {
this.aspectFactoryCache.put(beanName, factory);
}
advisors.addAll(classAdvisors);
...
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
...
List<Advisor> advisors = new ArrayList<>();
for (Method method : getAdvisorMethods(aspectClass)) {
// Prior to Spring Framework 5.2.7, advisors.size() was supplied as the declarationOrderInAspect
// to getAdvisor(...) to represent the "current position" in the declared methods list.
// However, since Java 7 the "current position" is not valid since the JDK no longer
// returns declared methods in the order in which they are declared in the source code.
// Thus, we now hard code the declarationOrderInAspect to 0 for all advice methods
// discovered via reflection in order to support reliable advice ordering across JVM launches.
// Specifically, a value of 0 aligns with the default value used in
// AspectJPrecedenceComparator.getAspectDeclarationOrder(Advisor).
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName);
if (advisor != null) {
advisors.add(advisor);
}
}
...
}
根据@Pointcut注解确认方法适用范围并对切入点执行顺序排序
private List<Method> getAdvisorMethods(Class<?> aspectClass) {
final List<Method> methods = new ArrayList<>();
ReflectionUtils.doWithMethods(aspectClass, method -> {
// Exclude pointcuts
if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
methods.add(method);
}
}, ReflectionUtils.USER_DECLARED_METHODS);
if (methods.size() > 1) {
methods.sort(METHOD_COMPARATOR);
}
return methods;
}
排序规则
public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFactory implements Serializable {
private static final Comparator<Method> METHOD_COMPARATOR;
static {
// Note: although @After is ordered before @AfterReturning and @AfterThrowing,
// an @After advice method will actually be invoked after @AfterReturning and
// @AfterThrowing methods due to the fact that AspectJAfterAdvice.invoke(MethodInvocation)
// invokes proceed() in a `try` block and only invokes the @After advice method
// in a corresponding `finally` block.
Comparator<Method> adviceKindComparator = new ConvertingComparator<>(
new InstanceComparator<>(
Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class),
(Converter<Method, Annotation>) method -> {
AspectJAnnotation<?> ann = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(method);
return (ann != null ? ann.getAnnotation() : null);
});
Comparator<Method> methodNameComparator = new ConvertingComparator<>(Method::getName);
METHOD_COMPARATOR = adviceKindComparator.thenComparing(methodNameComparator);
}
执行顺序
涉及类和顺序
频繁调用方法
org.springframework.aop.framework.ReflectiveMethodInvocation#proceed
public Object proceed() throws Throwable {
//获取下一个拦截器
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
//调用拦截器
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
一个切面各个切点执行顺序
org.springframework.aop.framework.CglibAopProxy.DynamicAdvisedInterceptor#intercept
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
...
//根据调用方法和调用方法所在类,找出匹配的
//Interception和Advice
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal;
// Check whether we only have one InvokerInterceptor: that is,
// no real advice, but just reflective invocation of the target.
if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
// We can skip creating a MethodInvocation: just invoke the target directly.
// Note that the final invoker must be an InvokerInterceptor, so we know
// it does nothing but a reflective operation on the target, and no hot
// swapping or fancy proxying.
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = methodProxy.invoke(target, argsToUse);
}
else {
// We need to create a method invocation...
//根据拦截器chain处理调用目标方法
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
}
retVal = processReturnType(proxy, target, method, retVal);
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
org.springframework.aop.framework.ReflectiveMethodInvocation#proceed
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
//当最后一个interceptor执行完后,调用目标方法
//并退出
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
//挨个执行拦截器链中的拦截器,从0开始
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// Evaluate dynamic method matcher here: static part will already have
// been evaluated and found to match.
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
// Dynamic matching failed.
// Skip this interceptor and invoke the next in the chain.
return proceed();
}
}
else {
// It's an interceptor, so we just invoke it: The pointcut will have
// been evaluated statically before this object was constructed.
//执行对应的拦截器
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
一定位于拦截器链执行的第一个,将当前调用上下文保存到线程本地,
供某些需要的切点获取这些信息
org.springframework.aop.interceptor.ExposeInvocationInterceptor#invoke
//Interceptor that exposes the current MethodInvocation as a thread-local object.
//We occasionally need to do this; for example, when a pointcut (e.g. an AspectJ expression pointcut) needs to know the full invocation context
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
MethodInvocation oldInvocation = invocation.get();
invocation.set(mi);
try {
//执行下一个拦截器
return mi.proceed();
}
finally {
invocation.set(oldInvocation);
}
}
org.springframework.aop.aspectj.AspectJAroundAdvice#invoke
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
if (!(mi instanceof ProxyMethodInvocation)) {
throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
}
//包装当前调用mi(CglibAopProxy$CglibMethodInvocation)
ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
JoinPointMatch jpm = getJoinPointMatch(pmi);
//调用环绕通知方法
return invokeAdviceMethod(pjp, jpm, null, null);
}
@Around("plc()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
//pjp.proceed();
//调用CglibAopProxy$CglibMethodInvocation.proceed()
Object proceed = pjp.proceed();
String name = pjp.getSignature().getName();
System.out.println("aroundLog:" + name);
return proceed;
}
org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor#invoke
public Object invoke(MethodInvocation mi) throws Throwable {
//调用before切入点的方法
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
//CglibAopProxy$CglibMethodInvocation.proceed()
//调用下一个拦截器
return mi.proceed();
}
org.springframework.aop.aspectj.AspectJAfterAdvice#invoke
public Object invoke(MethodInvocation mi) throws Throwable {
try {
//继续调用下一个拦截器
return mi.proceed();
}
finally {
//调用链结束后,调用after切入点的方法
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
}
org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor#invoke
public Object invoke(MethodInvocation mi) throws Throwable {
//继续调用下一个拦截器
Object retVal = mi.proceed();
//根据返回值调用afterReturn切入点方法
this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
return retVal;
}
process()
org.springframework.aop.aspectj.AspectJAfterThrowingAdvice#invoke
public Object invoke(MethodInvocation mi) throws Throwable {
try {
//继续调用下一个
return mi.proceed();
}
catch (Throwable ex) {
//只有当抛出异常是切点方法参数的的子类型时才执行
if (shouldInvokeOnThrowing(ex)) {
//调用afterThrow切点方法
invokeAdviceMethod(getJoinPointMatch(), null, ex);
}
throw ex;
}
}
第二个切面也是这个执行顺序一个切面各个切点执行顺序
最后执行目标方法,开始退出
org.springframework.aop.framework.ReflectiveMethodInvocation#proceed
public Object proceed() throws Throwable {
//这时最后一个拦截器也执行过了
//整个个拦截器链已经铺开
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
//执行被切面的方法,开始依次退出各个拦截器方法
return invokeJoinpoint();
}
前置通知例外,因为在拦截器链执行前,就已经调用过了
afterThrow只有在出现异常时才会执行
结果
beforeLog:getUserById
beforeTransaction:getUserById
getUserById
returningTransaction:getUserById
returningTransaction:user:1
afterTransaction:getUserById
aroundTransaction:getUserById
returningLog:getUserById
returningLog:user:1
afterLog:getUserById
aroundLog:getUserById