一,什么是责任链模式

责任链模式是一种设计模式。在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。

发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任。

责任链模式实现了请求者和处理者的解耦。

责任链模式涉及到的角色如下所示:

抽象处理者角色(Handler): 定义出一个处理请求的接口。接口定义出一个方法以设定和返回对下家的引用。这个角色通常由一个Java抽象类或者Java接口实现。

具体处理者角色(ConcreteHandler):具体处理者接到请求后,可以选择将请求处理掉,或者将请求传给下家。由于具体处理者持有对下家的引用,因此具体处理者可以将请求传给下家。

二,Spring的AOP中的责任链模式:

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

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

下面就模拟一下spring aop中的责任链,将多个Advice通知织入一个目标方法

三,模拟AOP中的责任链:

目标接口:

public interface ITargetService {void targetMethod(); //目标方法--切入点
}

目标类:

@Service
public class TargetServiceImpl implements ITargetService {/*** 目标方法,切入点*/@Overridepublic void targetMethod() {System.out.println("具体业务方法,正在执行具体业务逻辑...");}}

统一规范,定义一个Advice通知接口(拦截器)

public interface IMyInterceptor {void adviceMethod(ITargetService targetService);
}

前置通知(拦截器1)

@Service
public class BeforeInterceptorImpl implements IMyInterceptor {/*** 前置通知的方法* @param targetService*/@Overridepublic void adviceMethod(ITargetService targetService) {System.out.println("执行前置通知...");//调用执行目标方法的业务逻辑:targetService.targetMethod();}
}

后置通知(拦截器2)

@Service
public class AfterInterceptorImpl implements IMyInterceptor {/*** 后置通知的方法* @param targetService*/@Overridepublic void adviceMethod(ITargetService targetService) {//调用执行目标方法的业务逻辑:targetService.targetMethod();System.out.println("执行后置通知...");}
}

改造目标方法targetMethod,将多个通知织入目标方法,并以责任链模式的方式进行织入:

@Service
public class TargetServiceImpl implements ITargetService {private List<IMyInterceptor> myInterceptorList; //拦截器集合,即拦截器链//实例化目标类对象的时候,注入属性满足依赖;public TargetServiceImpl(List<IMyInterceptor> myInterceptorList) {this.myInterceptorList = myInterceptorList;}private int currentInterceptorIndex = -1; //该指针驱动责任链条向前执行/*** 目标方法,切入点*/@Overridepublic void targetMethod() {if (currentInterceptorIndex == this.myInterceptorList.size() - 1) {System.out.println("具体业务方法,正在执行具体业务逻辑...");return;}//获取拦截器链中当前的拦截器IMyInterceptor myInterceptor = this.myInterceptorList.get(++this.currentInterceptorIndex);//执行当前拦截器的Advice通知:myInterceptor.adviceMethod(this);}public TargetServiceImpl() { }
}

四,补充:AOP源码:

下面是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;}
}

整个执行流程:

Spring的AOP中的责任链模式相关推荐

  1. java 职责链模式_Java中的责任链模式

    java 职责链模式 当应有几个处理器来执行某项操作并为这些处理器定义特定顺序时,就需要采用责任链设计模式. 在运行时处理器顺序的可变性也很重要.模式的UML表示如下: 处理程序定义处理器对象的一般结 ...

  2. Java中的责任链模式

    当应有几个处理器来执行某项操作并为这些处理器定义特定顺序时,就需要采用责任链设计模式. 在运行时处理器顺序的可变性也很重要.模式的UML表示如下: 处理程序定义处理器对象的一般结构. 这里的" ...

  3. Spring中如何使用责任链模式

    2019独角兽企业重金招聘Python工程师标准>>> 关于责任链模式,其有两种形式,一种是通过外部调用的方式对链的各个节点调用进行控制,从而进行链的各个节点之间的切换:另一种是链的 ...

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

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

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

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

  6. 设计模式 | 责任链模式及典型应用

    本文的主要内容: 介绍责任链模式 请假流程示例 责任链模式总结 源码分析Tomcat Filter中的责任链模式 责任链模式 一个事件需要经过多个对象处理是一个挺常见的场景,譬如采购审批流程,请假流程 ...

  7. 最近学习了责任链模式

    2019独角兽企业重金招聘Python工程师标准>>> 前言 来菜鸟这个大家庭10个月了,总得来说比较融入了环境,同时在忙碌的工作中也深感技术积累不够,在优秀的人身边工作必须更加花时 ...

  8. 用三国演义解读:责任链模式

    故事 前两天,没事又刷了一遍三国演义,看到关羽身在曹营心在汉,听说刘备在袁绍那里,然后就上演了"过五关,斩六将". 关羽过五关斩六将主要内容: 第一关,东岭关,斩守将孔秀.东岭关, ...

  9. 三国演义:责任链模式

    故事 前两天,没事又刷了一遍三国演义,看到关羽身在曹营心在汉,听说刘备在袁绍那里,然后就上演了"过五关,斩六将". 关羽过五关斩六将主要内容: 第一关,东岭关,斩守将孔秀. 东岭关 ...

  10. 设计模式 - 责任链模式

    故事 前两天,没事又刷了一遍三国演义,看到关羽身在曹营心在汉,听说刘备在袁绍那里,然后就上演了"过五关,斩六将". 关羽过五关斩六将主要内容: 第一关,东岭关,斩守将孔秀. 东岭关 ...

最新文章

  1. 通过application.properties修改打开网页的方式
  2. 通过UltraISO来提取U盘启动盘的ISO镜像文件
  3. matlab仿真生成信号程序,信号与系统的MATLAB仿真
  4. After Opp is saved - change mode filling place
  5. 【高斯消元】球形空间产生器(luogu 4035/金牌导航 高斯消元-1)
  6. Mysql学习总结(49)——从开发规范、选型、拆分到减压
  7. ubuntu配置spyder和jupyter notebook的工作目录
  8. python快速入门 数据输出和基本类型 常用的循环遍历等
  9. CSS优先级、引入方式、Hack
  10. Layui 数据表格动态cols(字段)动态变化
  11. Java进阶之FileUpload完成上传
  12. python3 pyv8 linux,Python 3.4不能安装Pyv8模块
  13. 内向性格的人应该如何选择职业?
  14. 严正警告!!独处一室的人,请一定不要看文中介绍的URL,未成年也不能看![更新]
  15. NLP入门(八)使用CRF++实现命名实体识别(NER)
  16. Oracle空间数据库
  17. 增强 扫描王 源码_OpenCV探索之路(二十二):制作一个类“全能扫描王”的简易扫描软件...
  18. CISCO设备信息泄漏漏洞案例
  19. python用户输入文字_python中用户输入的关键字
  20. 论文阅读——A Deep Learning Design for improving Topology Coherence in Blood Vessel Segmentation

热门文章

  1. html控制手机回退键,向日葵手机控制手机全程指导
  2. java ArrayList 排序
  3. 梯度,雅克比矩阵和海森矩阵
  4. 大学C语言学习笔记(C语言程序设计第五版——谭浩强,翁凯C语言基础教程)基础、算法、程序结构、数组、函数、指针、枚举、结构、联合
  5. 电商微商已死、视商来袭
  6. ssh远程登录阿里云服务器
  7. 电商项目中遇到的经典问题
  8. 那些年,我们一起做过的KNX智能化控制经典案例!
  9. Zynq UltraScale+ MPSoC配置DDR4参数
  10. idea安装插件时一直转解决方法