美文网首页
spring--aop_2_源码分析之MethodInterce

spring--aop_2_源码分析之MethodInterce

作者: 达微 | 来源:发表于2021-11-04 11:26 被阅读0次

前提:

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功能

————————————————

版权声明:本文为CSDN博主「Jamin_Ma」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/convict_eva/article/details/81105144

相关文章

网友评论

      本文标题:spring--aop_2_源码分析之MethodInterce

      本文链接:https://www.haomeiwen.com/subject/qndqzltx.html