五Spring-AOP--4AOP拦截器链构建

五Spring-AOP--4AOP拦截器链构建

5.5.5.1 AdvisorChainFactory

通过该类获取作用在beanclass和method上的拦截器链chain。

public interface AdvisorChainFactory {

	//确定给定的advisorChain的configuration配置的MethodInterceptor的list
	List<Object> getInterceptorsAndDynamicInterceptionAdvice(Advised config, Method method, @Nullable Class<?> targetClass);

}
image-20220428132240569

子类DefaultAdvisorChainFactory实现该具体方法,生成拦截器链。

//DefaultAdvisorChainFactory:生成拦截器链
public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializable {

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

		// 拿到代理里面所有的通知们:getAdvisors
		List<Object> interceptorList = new ArrayList<>(config.getAdvisors().length);
		Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
		boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);
          //通过registry将advisor转换为interceptors
		AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();

    //遍历ProxyConfig中缓存的当前class的advisors集合
		for (Advisor advisor : config.getAdvisors()) { //1 
      //advisor为PointcutAdvisor的处理逻辑
			if (advisor instanceof PointcutAdvisor) { //2 
				// 转换为PointcutAdvisor
				PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
        //当当前advisor匹配到targetclass时(也就是目标类需要被此advisor增强拦截)
				if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) { //3 
          
/**…………………………………………………………………………………………构造拦截器链chain……………………………………………………………………………………………………………… */
          //registry.getInterceptors将advisor转换为MethodInterceptor,并创建拦截器链chain返回
					MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
          
					MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
          //如果当前当前advisor内的methodmatcher,能匹配到当前class的method上
					if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) { //4 
						// 动态匹配
            //(动态匹配,就是即使两个参数的match方法返回true,在运行时,最后依然会调用这个三个参数的matches方法)
						if (mm.isRuntime()) { //5 
						// Creating a new object instance in the getInterceptors() method
						// isn't a problem as we normally cache created chains.
                   //全部MethodInterceptors分别转换为InterceptorAndDynamicMethodMatcher
							for (MethodInterceptor interceptor : interceptors) {
                //如果mm.isRuntime为true动态匹配,chain链传入的是InterceptorAndDynamicMethodMatcher对象,在ReflectiveMethodInvocation的proceed的调用环节,匹配方法用的是三个参数的matches
								interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
							}
						} //5 
						// 静态匹配
						else {
              //直接将interceptors添加入list
							interceptorList.addAll(Arrays.asList(interceptors));
						}
					} //4 
				} //3 
			} //2
               //当advisor为引介introduction时的处理逻辑
			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;
	}
}

Advice-Advisor-MethodInterceptor转化逻辑全过程

构建拦截器链chain的逻辑:

首先通过pointcutAdvisor.getPointcut().getClassFilter.match(targetClass),判断当前对象targetClass是否需要切面增强,如果需要,通过AdvisorAdapterRegistry.getInterceptors(advisor),转换为interceptors对象;然后获取MethodMatcher,如果匹配到当前方法,且mm为动态匹配,那么将构建InterceptorAndDynamicMethodMatcher(interceptor, mm),加入list;如果为静态匹配,构建 interceptors直接加入list。

这个chain链,会在ReflectiveMethodInvocation的proceed中调用(动态匹配的需要调用methodMatcher的三个参数的matches来做匹配),详情看[5.4.4.2 ReflectiveMethodInvocation的proceed方法。](# 5.4.4.2 ReflectiveMethodInvocation)

图一:advice的获取并转换为advisor,并add入proxyFactory:

image-20220505201110228

图二:从proxyFactory中注册的advisor,转换为可执行的拦截器链,在proxy执行到代理方法时,拦截器链执行。

image-20230310121306034

注意:

从可知上面的过程,aopProxy的方法拦截,是动态拦截,生成的proxy类,只是一个动态代理的对象,具体方法或者拦截器的增强,是在执行到proxy的特定方法时,触发拦截器链执行,来完成代理增强的逻辑。

借助[DefaultAdvisorAdapterRegistry](#5.5.5 DefaultAdvisorAdapterRegistry)将Advisor集合转换成MethodInterceptor

image-20220428135131514

5.5.5.2 DefaultAdvisorAdapterRegistry

主要功能:

将Advice包装成Advisor(DefaultPointcutAdvisor);借助[AdvisorAdapter](#5.5.7 AdvisorAdapter)将Advisor包装成MethodInterceptor

public interface AdvisorAdapterRegistry {
     
	//将advice包装成Advisor对象
	Advisor wrap(Object advice) throws UnknownAdviceTypeException;

	//借助注册的AdvisorAdapter,将Advisor转换为MethodInterceptor[]
	MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException;

	//registry构造时,注册三个AdvisorAdapter
     //spring的aop的advisor不需要注册,针对特殊自定义的Advisor或者Advice,才需要注册
	void registerAdvisorAdapter(AdvisorAdapter adapter);

}

image-20220428140021081

public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {
		//通知器适配器集合
	private final List<AdvisorAdapter> adapters = new ArrayList<>(3);
  
  
	// 默认就支持这几种类型的适配器(AdvisorAdapter能将advisor转换为AOP可以拦截识别的MethodInterceptor对象)
	public DefaultAdvisorAdapterRegistry() {
		registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
		registerAdvisorAdapter(new AfterReturningAdviceAdapter());
		registerAdvisorAdapter(new ThrowsAdviceAdapter());
	}
  
  //将advice对象wrap包装转换为advisor对象
  @Override
	public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
/**…………………………………………………………待转换的为advisor的情况………………………………………………………………………………………… */
		if (adviceObject instanceof Advisor) {
			return (Advisor) adviceObject;
		}
		if (!(adviceObject instanceof Advice)) {
			throw new UnknownAdviceTypeException(adviceObject);
		}
    
/**…………………………………………………………待转换的为advice的情况………………………………………………………………………………………… */
		Advice advice = (Advice) adviceObject;
    //如果advice为MethodInterceptor
		if (advice instanceof MethodInterceptor) {
			//由于不需要advisorAdapter转换器,可之间构造advisor返回
			return new DefaultPointcutAdvisor(advice);
		}
    //如果advice为非MethodInterceptor的情况
		for (AdvisorAdapter adapter : this.adapters) {
			// Check that it is supported.
      //检测registry上所注册的advisorAdapter,是否有支持当前advice转换的,如果有,创建DefaultPointcutAdvisor
			if (adapter.supportsAdvice(advice)) {
				return new DefaultPointcutAdvisor(advice);
			}
		}
    //如果advisorAdapter没有支持转换advice的,则抛出异常
		throw new UnknownAdviceTypeException(advice);
	}

	@Override
	public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
		List<MethodInterceptor> interceptors = new ArrayList<>(3);
		Advice advice = advisor.getAdvice();
    //如果advice是MethodInterceptor类型,直接加入interceptors
		if (advice instanceof MethodInterceptor) {
			interceptors.add((MethodInterceptor) advice);
		}
    
    //遍历注册在registry内的
		for (AdvisorAdapter adapter : this.adapters) {
      //如果当前adapter支持转换当前advice
			if (adapter.supportsAdvice(advice)) {
        //通过getInterceptor转换,并添加入拦截器链interceptors上
				interceptors.add(adapter.getInterceptor(advisor));
			}
		}
		if (interceptors.isEmpty()) {
			throw new UnknownAdviceTypeException(advisor.getAdvice());
		}
		return interceptors.toArray(new MethodInterceptor[0]);
	}

  //注册AdvisorAdapter,存入缓存adapters中List<AdvisorAdapter>的advisor转换器list
	@Override
	public void registerAdvisorAdapter(AdvisorAdapter adapter) {
		this.adapters.add(adapter);
	}

5.5.5.3 AdvisorAdapter

功能:将AOP的advisor转换为spring可以拦截的Methodinterceptor

spring aop框架对BeforeAdvice、AfterAdvice、ThrowsAdvice三种通知类型的支持,实际上是借助适配器模式来实现的(aop的advisor转换为spring可以拦截的interceptor),这样的好处是使得框架允许用户向框架中加入自己想要支持的任何一种通知类型advice。AdvisorAdapter是一个适配器接口,它定义了自己支持的Advice类型,并且能把一个Advisor适配成MethodInterceptor`(这也是AOP联盟定义的接口),以下是它的定义

public interface AdvisorAdapter {
    // 判断此适配器是否支持特定的Advice  
    boolean supportsAdvice(Advice advice);  
    // 将一个Advisor适配成MethodInterceptor  
     //advisor是aop的,spring通过AdvisorAdapter将advisor转换为MethodInterceptor,使得spring可以拦截实现
    MethodInterceptor getInterceptor(Advisor advisor);  
}

image-20220428214132467

实现如下:

class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {

	@Override
	public boolean supportsAdvice(Advice advice) {
		return (advice instanceof MethodBeforeAdvice);
	}

	@Override
	public MethodInterceptor getInterceptor(Advisor advisor) {
		MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
		return new MethodBeforeAdviceInterceptor(advice);
	}

}


// 都转为了AOP联盟的MethodInterceptor 从而实现拦截统一的拦截工作
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {

  //转换后的interceptor持有MethodBeforeAdvice实例
	private MethodBeforeAdvice advice;

	public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
		Assert.notNull(advice, "Advice must not be null");
		this.advice = advice;
	}

	@Override
	public Object invoke(MethodInvocation mi) throws Throwable {
    //因为是methodBeforeAdvice,方法前增强,所以这里在执行链式调用mi.proceed之前,调用advice.before方法
		this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
		// 最终调用,实现了链式调用的效果
		return mi.proceed();
	}

}

如果我们想把自己定义的AdvisorAdapter注册到spring aop框架中,怎么办?

  1. 把我们自己写好得AdvisorAdapter放进Spring IoC容器

  2. 配置一个AdvisorAdapterRegistrationManager,它是一个BeanPostProcessor,它会检测所有的Bean。若是AdvisorAdapter类型,就:this.advisorAdapterRegistry.registerAdvisorAdapter((AdvisorAdapter) bean),注册操作,把自定义的adapter添加入registry的List<AdvisorAdapter> adapters缓存上;

  3. DefaultAdvisorAdapterRegistry.getInterceptors方法中,就可以将advisor转化为特定的methodInterceptor

    public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
    		List<MethodInterceptor> interceptors = new ArrayList<>(3);
    		Advice advice = advisor.getAdvice();
    		if (advice instanceof MethodInterceptor) {
    			interceptors.add((MethodInterceptor) advice);
    		}
      	
      	//遍历注册在registry的adapters上的AdvisorAdapter
    		for (AdvisorAdapter adapter : this.adapters) {
        //如果支持当前advice的转换,就getInterceptor转换为methodinterceptro上,并加入interceptor的list
    			if (adapter.supportsAdvice(advice)) {
    				interceptors.add(adapter.getInterceptor(advisor));
    			}
    		}
    		if (interceptors.isEmpty()) {
    			throw new UnknownAdviceTypeException(advisor.getAdvice());
    		}
    		return interceptors.toArray(new MethodInterceptor[0]);
    	}
    
posted @ 2023-03-10 17:16  LeasonXue  阅读(127)  评论(0编辑  收藏  举报