2023-09-16
原文作者:王伟王胖胖 原文地址: https://blog.csdn.net/wangwei19871103/article/details/105209011

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

202309162317470021.png

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通知是什么

其实他只是一个标记接口:

202309162317474342.png
我们的AOP最终都是这5类做的增强:

202309162317478423.png

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

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

阅读全文