45、Spring5.x源码之旅四十五Aspect注解解析二

  • ReflectiveAspectJAdvisorFactory的getAdvisor
    • getPointcut获取切点表达式
    • AbstractAspectJAdvisorFactory的findAspectJAnnotationOnMethod
  • InstantiationModelAwarePointcutAdvisorImpl构造方法
    • InstantiationModelAwarePointcutAdvisorImpl的instantiateAdvice
      • ReflectiveAspectJAdvisorFactory的getAdvice获取通知
  • Advice通知是什么

ReflectiveAspectJAdvisorFactory的getAdvisor

继续上一篇,我们现在已经获取到了切面对象里的方法,现在就是解析这些方法的注解来进行创建Advisor通知器,内部会创建Advice通知,怎么连切点都没分析就创建通知器了?其实切点就在这里面解析啦。

@Override
	@Nullable
	public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
			int declarationOrderInAspect, String aspectName) {
   
     

		validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
		//获取切点表达式
		AspectJExpressionPointcut expressionPointcut = getPointcut(
				candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
		if (expressionPointcut == null) {
   
     
			return null;
		}

		return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
				this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
	}

getPointcut获取切点表达式

首先当然去获取切点啦,先找下方法注解里面有没有AspectJ相关的注解Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class,没有当然就不用处理啦。有的话就要创建切点表达式,然后返回。

@Nullable
	private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
   
     
		AspectJAnnotation<?> aspectJAnnotation =//找AspectJAnnotation注解
				AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
		if (aspectJAnnotation == null) {
   
     
			return null;
		}

		AspectJExpressionPointcut ajexp =
				new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
		ajexp.setExpression(aspectJAnnotation.getPointcutExpression());//设置表达式
		if (this.beanFactory != null) {
   
     
			ajexp.setBeanFactory(this.beanFactory);
		}
		return ajexp;
	}

AbstractAspectJAdvisorFactory的findAspectJAnnotationOnMethod

遍历所有的AspectJ注解类型,寻找是否有该类的注解,有的话就封装成AspectJAnnotation返回。

private static final Class<?>[] ASPECTJ_ANNOTATION_CLASSES = new Class<?>[] {
   
     
			Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class};

	@Nullable
	protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
   
     
		for (Class<?> clazz : ASPECTJ_ANNOTATION_CLASSES) {
   
     //遍历所有注解,找到就返回
			AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) clazz);
			if (foundAnnotation != null) {
   
     
				return foundAnnotation;
			}
		}
		return null;
	}

InstantiationModelAwarePointcutAdvisorImpl构造方法

构造函数中最后的地方会实例化Advice
*

InstantiationModelAwarePointcutAdvisorImpl的instantiateAdvice

这里才是真的创建Advice通知。

	private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) {
   
     
		Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut,
				this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
		return (advice != null ? advice : EMPTY_ADVICE);
	}

ReflectiveAspectJAdvisorFactory的getAdvice获取通知

这个是最终的获取通知的方法,首先进行了一些验证,然后获得AspectJ的注解,根据注解类型进行创建,最后设置一些参数:

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

		Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
		validate(candidateAspectClass);

		AspectJAnnotation<?> aspectJAnnotation =
				AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
		if (aspectJAnnotation == null) {
   
     
			return null;
		}

		if (!isAspect(candidateAspectClass)) {
   
     
			throw new AopConfigException("Advice must be declared inside an aspect type: " +
					"Offending method '" + candidateAdviceMethod + "' in class [" +
					candidateAspectClass.getName() + "]");
		}

		if (logger.isDebugEnabled()) {
   
     
			logger.debug("Found AspectJ method: " + candidateAdviceMethod);
		}

		AbstractAspectJAdvice springAdvice;
		//通知类型
		switch (aspectJAnnotation.getAnnotationType()) {
   
     
			case AtPointcut:
				if (logger.isDebugEnabled()) {
   
     
					logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
				}
				return null;
			case AtAround:
				springAdvice = new AspectJAroundAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				break;
			case AtBefore:
				springAdvice = new AspectJMethodBeforeAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				break;
			case AtAfter:
				springAdvice = new AspectJAfterAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				break;
			case AtAfterReturning:
				springAdvice = new AspectJAfterReturningAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
				if (StringUtils.hasText(afterReturningAnnotation.returning())) {
   
     
					springAdvice.setReturningName(afterReturningAnnotation.returning());
				}
				break;
			case AtAfterThrowing:
				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);
		}
		springAdvice.calculateArgumentBindings();

		return springAdvice;
	}

Advice通知是什么

其实他只是一个标记接口:
*
我们的AOP最终都是这5类做的增强:
*

基本的切面解析和通知创建知道怎么来的,后面就看怎么把通知用上去了,是在初始化后的处理器AnnotationAwareAspectJAutoProxyCreatorpostProcessAfterInitialization方法里,下次讲吧。

好了,今天就到这里了,希望对学习理解有帮助,大神看见勿喷,仅为自己的学习理解,能力有限,请多包涵。