当一个对象在一条链上被多个拦截器拦截处理时,我们这样的设计模式称为责任链模式,它用于一个对象在多个角色中传递的场景.

SpringAOP就是利用动态代理和责任链模式实现的,当一个切面有多个织入时,这些需要织入的方法就形成了一个责任链,就像Filter链一样。

下面就模拟一下springaop中的责任链:

接口:

public interface Joinpoint {Object proceed() throws Throwable;
}
public interface MethodInvocation extends Joinpoint {
}

定义拦截器接口

public interface MethodInterceptor {Object invoke(MethodInvocation mi) throws Throwable;
}

定义前置通知,在目标方便调用前执行通知:

public class MethodBeforeAdviceInterceptor implements MethodInterceptor{@Overridepublic Object invoke(MethodInvocation mi) throws Throwable {System.out.println("I am BeforeAdvice");return mi.proceed();}
}

定义后置通知,在目标方法完成后执行通知:

public class AspectJAfterAdvice implements MethodInterceptor {@Overridepublic Object invoke(MethodInvocation mi) throws Throwable {Object var;try {var = mi.proceed();}finally {System.out.println("I am AfterAdvice");}return var;}
}

中间类,拦截器链调用逻辑:

public class ReflectiveMethodInvocation  implements MethodInvocation{List<MethodInterceptor> methodInterceptors;public ReflectiveMethodInvocation(List<MethodInterceptor> methodInterceptors) {this.methodInterceptors = methodInterceptors;}private int index = -1;@Overridepublic Object proceed() throws Throwable {Object var = null;if (index == this.methodInterceptors.size()-1) {System.out.println("真正的目标方法");return new String("ha");}else{var = methodInterceptors.get(++index).invoke(this);}return var;}}

测试类:

public class Test {public static void main(String[] args) throws Throwable {AspectJAfterAdvice aspectJAfterAdvice = new AspectJAfterAdvice();MethodBeforeAdviceInterceptor methodBeforeAdviceInterceptor = new MethodBeforeAdviceInterceptor();List<MethodInterceptor> methodInterceptors = new ArrayList<>();methodInterceptors.add(methodBeforeAdviceInterceptor);methodInterceptors.add(aspectJAfterAdvice);ReflectiveMethodInvocation reflectiveMethodInvocation = new ReflectiveMethodInvocation(methodInterceptors);reflectiveMethodInvocation.proceed();}
}

执行结果

I am BeforeAdvice
真正的目标方法
I am AfterAdvice

下面是springAOP中的源码

首先看JdkDynamicAopProxy类中的invoke方法:

final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Object oldProxy = null;boolean setProxyContext = false;TargetSource targetSource = this.advised.targetSource;Class<?> targetClass = null;Object target = null;Integer var10;try {if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {Boolean var20 = this.equals(args[0]);return var20;}if (this.hashCodeDefined || !AopUtils.isHashCodeMethod(method)) {if (method.getDeclaringClass() == DecoratingProxy.class) {Class var18 = AopProxyUtils.ultimateTargetClass(this.advised);return var18;}Object retVal;if (!this.advised.opaque && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) {retVal = AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);return retVal;}if (this.advised.exposeProxy) {oldProxy = AopContext.setCurrentProxy(proxy);setProxyContext = true;}target = targetSource.getTarget();if (target != null) {targetClass = target.getClass();}List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);if (chain.isEmpty()) {Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);} else {MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);retVal = invocation.proceed();}Class<?> returnType = method.getReturnType();if (retVal != null && retVal == target && returnType != Object.class && returnType.isInstance(proxy) && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {retVal = proxy;} else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {throw new AopInvocationException("Null return value from advice does not match primitive return type for: " + method);}Object var13 = retVal;return var13;}var10 = this.hashCode();} finally {if (target != null && !targetSource.isStatic()) {targetSource.releaseTarget(target);}if (setProxyContext) {AopContext.setCurrentProxy(oldProxy);}}return var10;}
看其中的
MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
retVal = invocation.proceed();
public Object proceed() throws Throwable {if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {return this.invokeJoinpoint();} else {Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher)interceptorOrInterceptionAdvice;//调用拦截器的执行方法,拦截器执行拦截逻辑后继续调用目标方法的proceed()方法,参考下面的两个拦截器invoke()实现return dm.methodMatcher.matches(this.method, this.targetClass, this.arguments) ? dm.interceptor.invoke(this) : this.proceed();} else {return ((MethodInterceptor)interceptorOrInterceptionAdvice).invoke(this);}}}
其中的before advice方法拦截器:
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {private MethodBeforeAdvice advice;public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {Assert.notNull(advice, "Advice must not be null");this.advice = advice;}public Object invoke(MethodInvocation mi) throws Throwable {this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());return mi.proceed();}
}
after advice方法拦截器
public class AspectJAfterAdvice extends AbstractAspectJAdvice implements MethodInterceptor, AfterAdvice, Serializable {public AspectJAfterAdvice(Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {super(aspectJBeforeAdviceMethod, pointcut, aif);}public Object invoke(MethodInvocation mi) throws Throwable {Object var2;try {var2 = mi.proceed();} finally {this.invokeAdviceMethod(this.getJoinPointMatch(), (Object)null, (Throwable)null);}return var2;}public boolean isBeforeAdvice() {return false;}public boolean isAfterAdvice() {return true;}
}

整个执行流程:

责任链模式在SpringAOP中的使用相关推荐

  1. 责任链模式在Android中的应用

    *本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布 责任链其实在Android中出现的频率还蛮高的,事件传递就是一种责任链机制.接下来我为大家介绍在开发应用时责任链的用处: 1.触摸 ...

  2. Android 架构之路(4)责任链模式在项目中的实际使用

    文章目录 前言 责任链模式定义 UML 类图: Demo 实现方式一: UML 类图: Demo 实现方式二: 项目实践 实现方式一: 实现方式二: 总结 前言 责任链模式(职责链模式)的运用在项目中 ...

  3. 责任链模式 php,编程中的那些套路——关于责任链模式

    该文章属于<编程中的那些经典套路--设计模式汇总>系列,并且以下内容基于语言PHP 今天来谈谈责任链模式,乍一听责任链模式好像很高级的一样,但是相信我,其实每位天朝的同学都十分熟悉这个模式 ...

  4. java设计模式之责任链模式以及在java中作用

    责任链模式是一种对象的行为模式.在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链.请求在这个链上传递,直到链上的某一个对象决定处理此请求.发出这个请求的客户端并不知道链上的哪一个 ...

  5. 【深入设计模式】责任链模式—责任链模式及责任链模式在源码中的应用

    文章目录 1. 责任链模式 1.1 责任链模式简介 1.2 责任链模式结构 1.3 责任链模式示例 2. 责任链模式在源码中的应用 2.1 Servlet 中的责任链模式 2.2 Spring 中的责 ...

  6. 责任链模式在复杂数据处理场景中的实战

    相信大家在日常的开发中都遇到过复杂数据处理和复杂数据校验的场景,本文从一线开发者的角度,分享了责任链模式在这种复杂数据处理场景下的实战案例,此外,作者在普通责任链模式的基础上进行了升级改造,可以适配更 ...

  7. 设计模式中的车轮战-责任链模式

    责任链模式在Android中的应用莫过于事件分发了,ViewGroup对事件分别给子View,从ViewTree的顶部至上而下地进行处理,直到事件被消化为止,这种方法在Android广播中也能看到 责 ...

  8. [转]《JAVA与模式》之责任链模式

    http://www.cnblogs.com/java-my-life/archive/2012/05/28/2516865.html 在阎宏博士的<JAVA与模式>一书中开头是这样描述责 ...

  9. 《JAVA与模式》之责任链模式

    2019独角兽企业重金招聘Python工程师标准>>> 详细请访问原博客:http://www.cnblogs.com/java-my-life/archive/2012/05/28 ...

最新文章

  1. 精美的电路图都是怎么画出来的?
  2. 科大星云诗社动态20211205
  3. 学习笔记之-java8的新特性-函数式接口,lambda表达式,方法引用,Stream API,Optional类
  4. 一道 3 行代码的 Python面试题,我懵逼了一天
  5. 说一下现在比较火的创业项目
  6. 不要让开源成为贸易战的牺牲品!
  7. 速修复!Netgear交换机曝3个严重的认证绕过漏洞
  8. Json 读写操作中含有中文时
  9. SQL多表连接查询时间最新的
  10. [整理]Linux压缩与解压缩命令整理。
  11. 如何搜mac_今日头条号权重怎么查?如何提高头条号权重?看完这篇你就懂了
  12. 详解各种光学仪器成像原理
  13. 怎么创建邮箱帐号?教育邮箱
  14. PHP 函数的完整参考手册
  15. 计算机无法读取手机内存,手机内存卡不能读取如何解决
  16. 为什么装了个visual studio就多了个dvd驱动器?
  17. 商汤的AI伴游小精灵(找最多子树)
  18. android IO流_Android 开发技术周报 Issue#265
  19. 案例研究|蜜雪冰城65亿背后的差异化商业模式创新
  20. 《Wireshark数据包分析实战》读书笔记

热门文章

  1. 金牌网管师系列教材北京发布会我的演讲稿
  2. WCP知识库 开源版 Win安装配置
  3. Qt中根据pc屏幕分辨率按比例修改窗口的大小
  4. 阿里云大数据组件零碎点总结(不定时更新)
  5. 沃尔玛erp系统功能分析
  6. 大商创 常见问题 mysql_【大商创常见问题】大商创v2.4及以上版本运费设置教程说明...
  7. Stereogram(极射赤面)投影--主要用于中高纬和极区的天气图
  8. 苹果库乐队怎么玩_自制手机铃声(苹果)
  9. APK瘦身记,如何实现高达53%的压缩效果
  10. git push 报错 Empty reply from server 或 Failed to connect to github.com port 443: Time out