Spring-AOP模块的Advisor分析

描述:Advisor模块是切面核心实现,需要重点掌握

使用结构:

              

UML结构图如下:

备注:IntroductionAdvisor:不使用pointcut,只作用于类(根据类的实现接口做筛选)。 todo:详细理解IntroductionAdvisor

PointcutAdvisor的UML结构图如下:

Pointcut:  一个切入点由一个类过滤器和一个方法匹配器组成; 维度是类和方法

public interface Pointcut {

   /**
    * Return the ClassFilter for this pointcut.
    * @return the ClassFilter (never {@code null})
    */
   ClassFilter getClassFilter();  //类过滤器
   /**
    * Return the MethodMatcher for this pointcut.
    * @return the MethodMatcher (never {@code null})
    */
   MethodMatcher getMethodMatcher(); //方法匹配器
   /**
    * Canonical Pointcut instance that always matches.
    */
   Pointcut TRUE = TruePointcut.INSTANCE;
}

实现类型 实现功能 例子
JdkRegexpMethodPointcut 使用正则表达式来匹配类型和方法  
AnnotationMatchingPointcut 通过类和方法是否实现特定注解进行匹配  
AbstractExpressionPointcut 使用表达式进行方法匹配  
AspectJExpressionPointcut 使用AspectJweaver来计算切入点表达式(pointcut expression),支持方法(Method)  

AbstractExpressionPointcut类UML结构图如下:

AspectJExpressionPointcut:使用AspectJweaver来计算切入点表达式(pointcut expression),支持方法(Method)

  核心方法:

 1.matches

    matches方法核心业务流程:

    

  

@Override
	public boolean matches(Method method, @Nullable Class<?> targetClass, Object... args) {
		obtainPointcutExpression();
		ShadowMatch shadowMatch = getShadowMatch(AopUtils.getMostSpecificMethod(method, targetClass), method);
		ShadowMatch originalShadowMatch = getShadowMatch(method, method);

		// Bind Spring AOP proxy to AspectJ "this" and Spring AOP target to AspectJ target,
		// consistent with return of MethodInvocationProceedingJoinPoint
		ProxyMethodInvocation pmi = null;
		Object targetObject = null;
		Object thisObject = null;
		try {
			MethodInvocation mi = ExposeInvocationInterceptor.currentInvocation();
			targetObject = mi.getThis();
			if (!(mi instanceof ProxyMethodInvocation)) {
				throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
			}
			pmi = (ProxyMethodInvocation) mi;
			thisObject = pmi.getProxy();
		}
		catch (IllegalStateException ex) {
			// No current invocation...
			if (logger.isDebugEnabled()) {
				logger.debug("Could not access current invocation - matching with limited context: " + ex);
			}
		}

		try {
			JoinPointMatch joinPointMatch = shadowMatch.matchesJoinPoint(thisObject, targetObject, args);

			/*
			 * Do a final check to see if any this(TYPE) kind of residue match. For
			 * this purpose, we use the original method's (proxy method's) shadow to
			 * ensure that 'this' is correctly checked against. Without this check,
			 * we get incorrect match on this(TYPE) where TYPE matches the target
			 * type but not 'this' (as would be the case of JDK dynamic proxies).
			 * <p>See SPR-2979 for the original bug.
			 */
			if (pmi != null && thisObject != null) {  // there is a current invocation
				RuntimeTestWalker originalMethodResidueTest = getRuntimeTestWalker(originalShadowMatch);
				if (!originalMethodResidueTest.testThisInstanceOfResidue(thisObject.getClass())) {
					return false;
				}
				if (joinPointMatch.matches()) {
					bindParameters(pmi, joinPointMatch);
				}
			}

			return joinPointMatch.matches();
		}
		catch (Throwable ex) {
			if (logger.isDebugEnabled()) {
				logger.debug("Failed to evaluate join point for arguments " + Arrays.asList(args) +
						" - falling back to non-match", ex);
			}
			return false;
		}
	}

 2.obtainPointcutExpression

 

3.getShadowMatch

   

AbstractBeanFactoryPointcutAdvisor:基于BeanFactory的抽象PointcutAdvisor,通过名称来引用BeanFactory中的Spring Bean 作为Advice(Spring AOP和IOC模块集成)

   类图如下:

   

核心方法:

 1.resetAdviceMonitor

2.getAdvice

DefaultAdvisorChainFactory:根据Advised对象的advisor列表重新生成MethodInterceptor chain

    核心方法:

    1.getInterceptorsAndDynamicInterceptionAdvice

    

@Override
	public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
			Advised config, Method method, @Nullable Class<?> targetClass) {

		// This is somewhat tricky... We have to process introductions first,
		// but we need to preserve order in the ultimate list.
		List<Object> interceptorList = new ArrayList<>(config.getAdvisors().length);
		Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
		boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);
		AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();

		for (Advisor advisor : config.getAdvisors()) {
			if (advisor instanceof PointcutAdvisor) {
				// Add it conditionally.
				PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
				if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
					MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
					MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
					if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {
						if (mm.isRuntime()) {
							// Creating a new object instance in the getInterceptors() method
							// isn't a problem as we normally cache created chains.
							for (MethodInterceptor interceptor : interceptors) {
								interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
							}
						}
						else {
							interceptorList.addAll(Arrays.asList(interceptors));
						}
					}
				}
			}
			else if (advisor instanceof IntroductionAdvisor) {
				IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
				if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
					Interceptor[] interceptors = registry.getInterceptors(advisor);
					interceptorList.addAll(Arrays.asList(interceptors));
				}
			}
			else {
				Interceptor[] interceptors = registry.getInterceptors(advisor);
				interceptorList.addAll(Arrays.asList(interceptors));
			}
		}

		return interceptorList;
	}

  执行流程如下:

  遍历config对象的Advisor列表类型,采取不同的过滤方式:

  1.Advisor的具体实现类型是PointcutAdvisor,通过class和method match 进行过滤

  2.Advisor的具体实现类型是IntroductionAdvisor,通过class match进行过滤

  3.其他类型直接通过

ReflectiveAspectJAdvisorFactory:用于创建AspectJ类型的Spring AOP advisor的工厂类;在使用AspectJ 5注解的类型上,通过反射的方式调用相应的advice方法

核心方法:

  1. getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory)

    执行流程:

       a.遍历使用AspectJ注解对象的包含Around,Before,After,AfterReturning和AfterThrowing注解的方法,调用getAdvisor方法来生 成Advisor

       b.判断当前类型的Aspect注解设置的延迟初始化属性,决定是否生成SyntheticInstantiationAdvisor

       c.遍历当前类型的使用DeclareParents注解的字段,生成DeclareParentsAdvisor

     2. getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
int declarationOrderInAspect, String aspectName)

    执行流程:

        

    3. getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName)

    执行流程:

    根据方法上的Aspect注解,生成对应的Advice

注解类型 advice类型 分析链接

AtBefore

AspectJMethodBeforeAdvice

 

AtAfter

AspectJAfterAdvice

 

AtAfterReturning

AspectJAfterReturningAdvice

 

AtAfterThrowing

AspectJAfterThrowingAdvice

 

AtAround

AspectJAroundAdvice  

猜你喜欢

转载自blog.csdn.net/zuojunyuan/article/details/89004268