spring--aop_2_源码分析之MethodInterceptor

前提:

https://blog.csdn.net/convict_eva/article/details/81084833

https://blog.csdn.net/convict_eva/article/details/81101432

前两篇分析了aop 两种方式实现的大致流程和方式,在这两种实现方式中都有一个很重要的方法获取拦截器链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
所有的aop增强方法都封装在一个个拦截器中,然后根据这个拦截器链的调用进行增强。

此方法的实现是在advised 对象实现的(advised 是 AdvisedSupport 对象的实例,ProxyFactoryBean 是AdvisedSupport 子类)
 

public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
	MethodCacheKey cacheKey = new MethodCacheKey(method);
	//这里使用了缓存来提高效率,第一次获取还是要创建的。
	//使用了 advisorChainFactory 生成拦截器链,advisorChainFactory 是 DefaultAdvisorChainFactory 的实例
	List<Object> cached = this.methodCache.get(cacheKey);
	if (cached == null) {
		cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
				this, method, targetClass);
		this.methodCache.put(cacheKey, cached);
	}
	return cached;
}

advisorChainFactory.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.
	//初始化拦截器链,大小是通知器个数。这个配置就是 ProxyFactoryBean 的 interceptNames 的属性配置。
	List<Object> interceptorList = new ArrayList<>(config.getAdvisors().length);
	
	Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
	boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);
	
	//获取 AdvisorAdapterRegistry 实例,AdvisorAdapterRegistry被称为“注册器”
	//利用它来对从ProxyFactoryBean 配置中得到的通知器进行适配,从而获得相应的拦截器,再把拦截器加入到拦截器链中
	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)) {
			
				//通过  AdvisorAdapterRegistry 获取拦截器,这个方法封装了advice 织入的实现入口
				MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
				
				//获取 MethodMatcher ,用来匹配目标方法,如果匹配就放入到拦截器链中。pointcut 就是在这里使用的
				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;
}

通过GlobalAdvisorAdapterRegistry 获取一个单例的 AdvisorAdapterRegistry 实例
AdvisorAdapterRegistry 的实现是 DefaultAdvisorAdapterRegistry
DefaultAdvisorAdapterRegistry.getInterceptors() 方法封装了advice 织入实现的入口

注:在ProxyFactoryBean 中已经把配置的advice封装成了 Advisor,第一篇有介绍。

DefaultAdvisorAdapterRegistry 类源码分析:

public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {

	//advisor 适配器列表
	private final List<AdvisorAdapter> adapters = new ArrayList<>(3);


	/**
	 * Create a new DefaultAdvisorAdapterRegistry, registering well-known adapters.
		定义了3个适配器, 就是这3个适配器为aop提供编织能力。
		这3个适配器和spring aop提供的advice增强功能相对就的
		这3个是spring aop advice的封装实现
	 */
	public DefaultAdvisorAdapterRegistry() {
		registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
		registerAdvisorAdapter(new AfterReturningAdviceAdapter());
		registerAdvisorAdapter(new ThrowsAdviceAdapter());
	}
	
	//省略方法......

	@Override
	public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {

		List<MethodInterceptor> interceptors = new ArrayList<>(3);
		//从advisor通知器中获取advice通知
		Advice advice = advisor.getAdvice();
		if (advice instanceof MethodInterceptor) {
			//如果是MethodInterceptor 直接加入到MethodInterceptor list 中不需要适配
			interceptors.add((MethodInterceptor) advice);
		}
		//对通知器进行适配,使用构造时已经配置好的adapter(上面3种adapter)
		//然后从对应的adapter 中取出封装好的aop编织功能的拦截器
		//通过adapter.getInterceptor() 方法返回对应的是3种 MethodInterceptor。
		//这里就是第一篇分析的invoke获取拦截器链调用的 MethodInterceptor
		for (AdvisorAdapter adapter : this.adapters) {
			if (adapter.supportsAdvice(advice)) {
				interceptors.add(adapter.getInterceptor(advisor));
			}
		}
		if (interceptors.isEmpty()) {
			throw new UnknownAdviceTypeException(advisor.getAdvice());
		}
		return interceptors.toArray(new MethodInterceptor[0]);
	}

	//可以自己定义adapter
	@Override
	public void registerAdvisorAdapter(AdvisorAdapter adapter) {
		this.adapters.add(adapter);
	}
}

adapter 有三种实现方式
这里使用MethodBeforeAdviceAdapter说明:就是判断一下advice类型,然后把advice 封装成MethodInterceptor
 

class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {

	//这里验证是否是 MethodBeforeAdvice 类型
	@Override
	public boolean supportsAdvice(Advice advice) {
		return (advice instanceof MethodBeforeAdvice);
	}
	
	@Override
	public MethodInterceptor getInterceptor(Advisor advisor) {
		//获取advice,创建 MethodBeforeAdviceInterceptor 对象并返回
		MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
		return new MethodBeforeAdviceInterceptor(advice);
	}
}

这里获取了advisor 对应的 MethodInterceptor之后,就要对这MethodInterceptor 进行匹配了
匹配使用的是通过 advisor.getPointcut().getMethodMatcher() 获取到 MethodMatcher 对象进行匹配验证的。

 

总结:
    通过配置 ProxyFactoryBean interceptorNames 属性来配置advice,ProxyFactoryBean 调用 initializeAdvisorChain() 方法把这些配置解析成 advisor链(advisor 包含了advice 和 pointcut)。
    在代理对象调用目标方法时,通过 DefaultAdvisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice() 方法获取到拦截器链,这个方法又是调用 DefaultAdvisorAdapterRegistry.getInterceptors() 方法生成的拦截器链。
    spring aop 就是通过拦截器模式调用这些生成的拦截器实现的aop功能

 

 

    原文作者:Spring MVC
    原文地址: https://blog.csdn.net/convict_eva/article/details/81105144
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞