这一次搞懂Spring代理创建+AOP链式调用过程

之前就说过切面的定义,是切点和增强的组合,所以这里首先通过getPointcut获取到注解对象,然后new了一个Pointcut对象,并将表达式设置进去。然后在getAdvisor方法中最后new了一个InstantiationModelAwarePointcutAdvisorImpl对象:

public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {

this.declaredPointcut = declaredPointcut;
this.declaringClass = aspectJAdviceMethod.getDeclaringClass();
this.methodName = aspectJAdviceMethod.getName();
this.parameterTypes = aspectJAdviceMethod.getParameterTypes();
this.aspectJAdviceMethod = aspectJAdviceMethod;
this.aspectJAdvisorFactory = aspectJAdvisorFactory;
this.aspectInstanceFactory = aspectInstanceFactory;
this.declarationOrder = declarationOrder;
this.aspectName = aspectName;

if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
// Static part of the pointcut is a lazy type.
Pointcut preInstantiationPointcut = Pointcuts.union(
aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);

// Make it dynamic: must mutate from pre-instantiation to post-instantiation state.
// If it’s not a dynamic pointcut, it may be optimized out
// by the Spring AOP infrastructure after the first evaluation.
this.pointcut = new PerTargetInstantiationModelPointcut(
this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);
this.lazy = true;
}
else {
// A singleton aspect.
this.pointcut = this.declaredPointcut;
this.lazy = false;
//这个方法重点看看,创建advice对象
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
}
}

这个就是我们的切面类,在其构造方法的最后通过instantiateAdvice创建了Advice对象。注意这里传进来的declarationOrder参数,它就是循环method时的序号,其作用就是赋值给这里的declarationOrder属性以及Advice的declarationOrder属性,在后面排序时就会通过这个序号来比较,因此Advice的执行顺序是固定的,至于为什么要固定,后面分析完AOP链式调用过程自然就明白了。

public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {

//获取有@Aspect注解的类
Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
validate(candidateAspectClass);

//找到candidateAdviceMethod方法上面的注解,并且包装成AspectJAnnotation对象,这个对象中就有注解类型
AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
}

AbstractAspectJAdvice springAdvice;

//根据不同的注解类型创建不同的advice类实例
switch (aspectJAnnotation.getAnnotationType()) {
case AtPointcut:
if (logger.isDebugEnabled()) {
logger.debug(“Processing pointcut '” + candidateAdviceMethod.getName() + “'”);
}
return null;
case AtAround:
//实现了MethodInterceptor接口
springAdvice = new AspectJAroundAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtBefore:
//实现了MethodBeforeAdvice接口,没有实现MethodInterceptor接口
springAdvice = new AspectJMethodBeforeAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtAfter:
//实现了MethodInterceptor接口
springAdvice = new AspectJAfterAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtAfterReturning:
//实现了AfterReturningAdvice接口,没有实现MethodInterceptor接口
springAdvice = new AspectJAfterReturningAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterReturningAnnotation.returning())) {
springAdvice.setReturningName(afterReturningAnnotation.returning());
}
break;
case AtAfterThrowing:
//实现了MethodInterceptor接口
springAdvice = new AspectJAfterThrowingAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
}
break;
default:
throw new UnsupportedOperationException(
"Unsupported advice type on method: " + candidateAdviceMethod);
}

// Now to configure the advice…
springAdvice.setAspectName(aspectName);
springAdvice.setDeclarationOrder(declarationOrder);
String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
if (argNames != null) {
springAdvice.setArgumentNamesFromStringArray(argNames);
}

//计算argNames和类型的对应关系
springAdvice.calculateArgumentBindings();

return springAdvice;
}

这里逻辑很清晰,就是拿到方法上的注解类型,根据类型创建不同的增强Advice对象:AspectJAroundAdvice、AspectJMethodBeforeAdvice、AspectJAfterAdvice、AspectJAfterReturningAdvice、AspectJAfterThrowingAdvice。完成之后通过calculateArgumentBindings方法进行参数绑定,感兴趣的可自行研究。这里主要看看几个Advice的继承体系:

可以看到有两个Advice是没有实现MethodInterceptor接口的:AspectJMethodBeforeAdvice和AspectJAfterReturningAdvice。而MethodInterceptor有一个invoke方法,这个方法就是链式调用的核心方法,但那两个没有实现该方法的Advice怎么处理呢?稍后会分析。
到这里切面对象就创建完成了,接下来就是判断当前创建的Bean实例是否和这些切面匹配以及对切面排序。匹配过程比较复杂,对理解主流程也没什么帮助,所以这里就不展开分析,感兴趣的自行分析(AbstractAdvisorAutoProxyCreator.findAdvisorsThatCanApply())。下面看看排序的过程,回到AbstractAdvisorAutoProxyCreator.findEligibleAdvisors方法:

protected List findEligibleAdvisors(Class<?> beanClass, String beanName) {
//找到候选的切面,其实就是一个寻找有@Aspectj注解的过程,把工程中所有有这个注解的类封装成Advisor返回
List candidateAdvisors = findCandidateAdvisors();

//判断候选的切面是否作用在当前beanClass上面,就是一个匹配过程。。现在就是一个匹配
List eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
//对有@Order@Priority进行排序
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值