责任链模式原理详解和源码实例以及Spring AOP拦截器链的执行源码如何使用责任链模式?

前言

  本文首先介绍了责任链的基本原理,并附带一个例子说明责任链模式,确保能够理解责任链的前提下,在进行Spring AOP执行责任链的源码分析。责任链模式允许将多个处理对象连接成链,请求沿着链传递,直到被处理或结束。每个处理者可以选择处理请求或传递给下一个。

  Spring AOP的拦截器链,拦截器或者过滤器链,都是典型的责任链应用。比如,当一个方法被调用时,多个拦截器按顺序执行,每个拦截器可以决定是否继续执行链中的下一个。

  深入Spring AOP的源码部分,特别是拦截器链的执行过程。比如,在Spring AOP中,当调用一个被增强的方法时,会创建一个MethodInvocation对象,其中包含拦截器链。每个拦截器都是一个Advice,比如MethodInterceptor。这时候,责任链模式的应用可能体现在拦截器的依次调用上,每个拦截器处理完后调用下一个,直到最后一个拦截器执行实际的方法。

  具体分析Spring的源码,比如ReflectiveMethodInvocation类的proceed方法。这个方法可能负责按顺序调用拦截器链中的每个拦截器,直到所有拦截器处理完毕,最后调用目标方法。这个流程是否符合责任链模式的结构?是的,每个拦截器处理请求,并决定是否传递下去。

  可能还需要比较责任链模式的不同变体,比如纯的责任链(每个处理者必须处理请求)和不纯的(可以传递)。Spring AOP的拦截器链属于后者,每个拦截器都可以选择是否继续传递,或者在处理前后执行某些操作,然后继续传递。

  另外,Spring AOP的基本原理不在本文中介绍了,详情请看以往文章,有更加详细的表述,有理论和源码的解析。文章:Spring AOP源码解析

  实际应用场景本文也涉及到,如何自定义拦截器,如何调整拦截器链的顺序,或者如何利用责任链模式实现类似的功能。这些实际应用案例可以增强回答的实用性。

  最后,确保回答结构清晰,先解释责任链模式,再结合Spring源码详细说明,最后总结其优势和应用场景。需要避免过于冗长的代码分析,而是突出重点部分,比如关键类和方法的调用流程。


责任链模式原理详解与源码实例


一、责任链模式(Chain of Responsibility Pattern)原理

核心思想:将多个处理对象连成一条链,请求沿链传递,直到有一个处理对象处理它或链结束。每个处理对象可选择处理请求或传递给下一个对象。

1. 模式结构
角色职责
Handler(抽象处理者)定义处理请求的接口,通常包含指向下一个处理者的引用(nextHandler)。
ConcreteHandler具体处理者,实现处理逻辑,或决定是否将请求传递到下一个处理者。
Request请求对象,封装请求的上下文数据。
2. 类图
+----------------+          +-------------------+
|   Handler      | <|-------| ConcreteHandlerA  |
+----------------+          +-------------------+
| +nextHandler   |          | +handleRequest()  |
| +handleRequest()|         +-------------------+
+----------------+                   ^
        |                            |
        |                            |
+-------------------+
| ConcreteHandlerB  |
+-------------------+
| +handleRequest()  |
+-------------------+
3. 执行流程
  1. 客户端将请求发送到责任链的第一个处理者。
  2. 每个处理者决定是否处理该请求:
    • 若处理,则终止传递。
    • 若不处理,则调用 nextHandler.handleRequest()
  3. 请求沿链传递,直到被处理或链结束。

二、责任链模式源码实例
1. 抽象处理者(Handler)
public abstract class Handler {
    protected Handler nextHandler; // 指向下一个处理者

    public void setNextHandler(Handler nextHandler) {
        this.nextHandler = nextHandler;
    }

    public abstract void handleRequest(Request request);
}
2. 具体处理者(ConcreteHandler)
public class ConcreteHandlerA extends Handler {
    @Override
    public void handleRequest(Request request) {
        if (canHandle(request)) {
            System.out.println("ConcreteHandlerA 处理请求: " + request.getData());
        } else if (nextHandler != null) {
            nextHandler.handleRequest(request); // 传递给下一个处理者
        }
    }

    private boolean canHandle(Request request) {
        return request.getType().equals("A");
    }
}

public class ConcreteHandlerB extends Handler {
    @Override
    public void handleRequest(Request request) {
        if (canHandle(request)) {
            System.out.println("ConcreteHandlerB 处理请求: " + request.getData());
        } else if (nextHandler != null) {
            nextHandler.handleRequest(request); // 传递给下一个处理者
        }
    }

    private boolean canHandle(Request request) {
        return request.getType().equals("B");
    }
}
3. 请求对象(Request)
public class Request {
    private String type; // 请求类型
    private String data; // 请求数据

    public Request(String type, String data) {
        this.type = type;
        this.data = data;
    }

    public String getType() { return type; }
    public String getData() { return data; }
}
4. 客户端调用
public class Client {
    public static void main(String[] args) {
        // 创建责任链
        Handler handlerA = new ConcreteHandlerA();
        Handler handlerB = new ConcreteHandlerB();
        handlerA.setNextHandler(handlerB);

        // 发送请求
        Request request1 = new Request("A", "请求1");
        Request request2 = new Request("B", "请求2");
        handlerA.handleRequest(request1); // 由 ConcreteHandlerA 处理
        handlerA.handleRequest(request2); // 由 ConcreteHandlerB 处理
    }
}

输出结果

ConcreteHandlerA 处理请求: 请求1
ConcreteHandlerB 处理请求: 请求2

三、Spring AOP 拦截器链中的责任链模式

Spring AOP 通过 拦截器链(Interceptor Chain) 实现方法增强(如事务、日志),其核心设计正是基于责任链模式。

1. 核心组件
组件职责
MethodInvocation封装被代理方法的调用上下文(类似 Request)。
MethodInterceptor拦截器接口(类似 Handler),定义增强逻辑。
ReflectiveMethodInvocation具体责任链实现,管理拦截器链的调用顺序。
2. 源码解析
(1)拦截器链的创建

在生成代理对象时,Spring 会将所有匹配的拦截器(如 MethodInterceptor)按顺序组合成链。

入口AdvisedSupport#getInterceptorsAndDynamicInterceptionAdvice

public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
    // 获取所有拦截器(包括事务、日志等)
    List<Object> interceptorList = new ArrayList<>();
    for (Advisor advisor : this.advisors) {
        if (advisor instanceof PointcutAdvisor) {
            // 匹配拦截器是否适用于当前方法
            if (((PointcutAdvisor) advisor).getPointcut().getMethodMatcher().matches(method, targetClass)) {
                interceptorList.add(advisor.getAdvice());
            }
        }
    }
    return interceptorList;
}
(2)责任链的触发

代理对象调用方法时,触发 ReflectiveMethodInvocation#proceed(),按顺序执行拦截器链。该方法类似于递归执行,递归方法也是有终止条件的,请注意区分。

源码ReflectiveMethodInvocation

public class ReflectiveMethodInvocation implements ProxyMethodInvocation {
    private final Object target;          // 目标对象
    private final Method method;          // 目标方法
    private final Object[] arguments;     // 方法参数
    private final List<Object> interceptorsAndDynamicMethodMatchers; // 拦截器链
    private int currentInterceptorIndex = -1; // 当前拦截器索引

    public Object proceed() throws Throwable {
        // 1. 所有拦截器执行完毕,调用原始方法
        if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
            return invokeJoinpoint();
        }

        // 2. 获取下一个拦截器
        Object interceptorOrInterceptionAdvice =
            this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);

        // 3. 执行拦截器逻辑
        if (interceptorOrInterceptionAdvice instanceof MethodInterceptor) {
            MethodInterceptor mi = (MethodInterceptor) interceptorOrInterceptionAdvice;
            return mi.invoke(this); // 将当前 MethodInvocation 传递给拦截器
        } else {
            // 动态匹配器处理(略)
        }
    }

    // 调用原始方法
    protected Object invokeJoinpoint() throws Throwable {
        return AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments);
    }
}
(3)拦截器的执行逻辑

每个 MethodInterceptor 拦截器决定是否继续传递链(调用 proceed())或终止。

示例:Spring 事务拦截器 TransactionInterceptor

public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor {
    public Object invoke(MethodInvocation invocation) throws Throwable {
        // 1. 开启事务
        TransactionInfo txInfo = createTransactionIfNecessary(invocation.getMethod(), targetClass);

        try {
            // 2. 继续执行拦截器链(责任链传递)
            Object retVal = invocation.proceed();

            // 3. 提交事务
            commitTransactionAfterReturning(txInfo);
            return retVal;
        } catch (Throwable ex) {
            // 4. 回滚事务
            completeTransactionAfterThrowing(txInfo, ex);
            throw ex;
        }
    }
}

四、责任链模式在 Spring AOP 中的设计优势
  1. 灵活扩展
    新增拦截器只需实现 MethodInterceptor 并注册到链中,无需修改现有代码。

  2. 逻辑解耦
    每个拦截器专注单一职责(如事务、日志),通过链式调用组合功能。

  3. 动态控制流程
    拦截器可决定是否继续调用链(如权限校验失败时直接抛出异常终止流程)。

  4. 执行顺序可控
    拦截器链的顺序可通过 @Order 注解或实现 Ordered 接口调整。


五、实际应用场景与自定义拦截器
1. 自定义拦截器示例
public class LoggingInterceptor implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        System.out.println("方法调用前: " + invocation.getMethod().getName());
        Object result = invocation.proceed(); // 继续链
        System.out.println("方法调用后: " + invocation.getMethod().getName());
        return result;
    }
}
2. 配置拦截器链

在 Spring 配置中注册拦截器:

<bean id="loggingInterceptor" class="com.example.LoggingInterceptor"/>
<bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor"/>

<aop:config>
    <aop:advisor advice-ref="loggingInterceptor" order="1"/>
    <aop:advisor advice-ref="transactionInterceptor" order="2"/>
</aop:config>
3. 执行顺序

拦截器按 order 值从小到大依次执行:

LoggingInterceptor(前置日志) → TransactionInterceptor(事务管理) → 目标方法

六、总结
  • 责任链模式核心:解耦请求发送者与处理者,允许多个对象按链式处理请求。
  • Spring AOP 实现:通过 ReflectiveMethodInvocation 管理拦截器链,每个 MethodInterceptor 按责任链模式依次执行。
  • 优势:灵活扩展、职责分离、动态流程控制。
  • 应用场景:事务管理、日志记录、权限校验、性能监控等切面功能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/973282.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

深入了解 DevOps 基础架构:可追溯性的关键作用

在当今竞争激烈的软件环境中&#xff0c;快速交付强大的应用程序至关重要。尽管如此&#xff0c;在不影响质量的情况下保持速度可能是一项艰巨的任务&#xff0c;这就是 DevOps 中的可追溯性发挥作用的地方。通过提供软件开发生命周期 &#xff08;SDLC&#xff09; 的透明视图…

由浅入深学习大语言模型RLHF(PPO强化学习- v1浅浅的)

最近&#xff0c;随着DeepSeek的爆火&#xff0c;GRPO也走进了视野中。为了更好的学习GRPO&#xff0c;需要对PPO的强化学习有一个深入的理解&#xff0c;那么写一篇文章加深理解吧。纵观网上的文章&#xff0c;要么说PPO原理&#xff0c;各种复杂的公式看了就晕&#xff0c;要…

【Java八股文】08-计算机网络面试篇

【Java八股文】08-计算机网络面试篇 计算机网络面试篇网络模型网络OSI模型和TCP/IP模型分别介绍一下键入网址到网页显示&#xff0c;期间发生了什么&#xff1f; 应用层- HTTP应用层有哪些协议&#xff1f;HTTP是什么及HTTP报文有哪些部分&#xff1f;HTTP是怎么传输数据的HTTP…

【Linux】Linux 文件系统——有关 inode 不足的案例

ℹ️大家好&#xff0c;我是练小杰&#xff0c;今天周二了&#xff0c;明天星期三&#xff0c;还有三天就是星期五了&#xff0c;坚持住啊各位&#xff01;&#xff01;&#xff01;&#x1f606; 本文是对之前Linux文件权限中的inode号进行实例讨论&#xff0c;看到博客有错误…

SpringBoot整合Redis和Redision锁

参考文章 1.Redis 1.导入依赖 <!--Redis依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.apache.c…

亲测可用,IDEA中使用满血版DeepSeek R1!支持深度思考!免费!免配置!

作者&#xff1a;程序员 Hollis 之前介绍过在IDEA中使用DeepSeek的方案&#xff0c;但是很多人表示还是用的不够爽&#xff0c;比如用CodeChat的方案&#xff0c;只支持V3版本&#xff0c;不支持带推理的R1。想要配置R1的话有特别的麻烦。 那么&#xff0c;今天&#xff0c;给…

一周学会Flask3 Python Web开发-Debug模式开启

锋哥原创的Flask3 Python Web开发 Flask3视频教程&#xff1a; 2025版 Flask3 Python web开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili 默认情况&#xff0c;项目开发是普通模式&#xff0c;也就是你修改了代码&#xff0c;必须重启项目&#xff0c;新代码才生效&…

某手sig3-ios算法 Chomper黑盒调用

Chomper-iOS界的Unidbg 最近在学习中发现一个Chomper框架&#xff0c;Chomper 是一个模拟执行iOS可执行文件的框架&#xff0c;类似于安卓端大名鼎鼎的Unidbg。 这篇文章使用Chomper模拟执行某手的sig3算法&#xff0c;初步熟悉该框架。这里只熟悉模拟执行步骤以及一些常见的…

PyTorch 深度学习框架中 torch.cuda.empty_cache() 的妙用与注意事项

&#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ 在使用 PyTorch 进行深度学习模型训练与调优过程中&#xff0c;torch.cuda.empty_cache() 方法作为一种高效工具被广泛采用&#xff1b;但其正确应用要求充分理解该方法的功能及最佳实践。下文将对该方…

巧用GitHub的CICD功能免费打包部署前端项目

近年来&#xff0c;随着前端技术的发展&#xff0c;前端项目的构建和打包过程变得越来越复杂&#xff0c;占用的资源也越来越多。我有一台云服务器&#xff0c;原本打算使用Docker进行部署&#xff0c;以简化操作流程。然而&#xff0c;只要执行sudo docker-compose -f deploy/…

配置Api自动生成

我的飞书:https://rvg7rs2jk1g.feishu.cn/docx/TVlJdMgYLoDJrsxAwMgcCE14nxt 使用Springfox Swagger生成API&#xff0c;并导入Postman&#xff0c;完成API单元测试 Swagger: 是一套API定义的规范&#xff0c;按照这套规范的要求去定义接口及接口相关信息&#xff0c;再通过可…

【JMeter使用-2】JMeter中Java Request采样器的使用指南

Apache JMeter 是一款功能强大的性能测试工具&#xff0c;支持多种协议和测试场景。除了内置的采样器&#xff08;如HTTP请求、FTP请求等&#xff09;&#xff0c;JMeter还允许通过 Java Request采样器 调用自定义的Java代码&#xff0c;从而实现更复杂的测试逻辑。本文将详细介…

将Google文档导入WordPress:简单实用的几种方法

Google文档是内容创作者非常实用的写作工具。它支持在线编辑、多人协作&#xff0c;并能够自动保存内容。但当我们想把Google文档中的内容导入WordPress网站时&#xff0c;可能会遇到一些小麻烦&#xff0c;比如格式错乱、图片丢失等问题。本文将为大家介绍几种简单实用的方法&…

Android开发-深入解析Android中的AIDL及其应用场景

深入解析 Android 中的 AIDL 及其应用场景 1. 前言2. AIDL 的核心概念3. AIDL 的实现步骤3.1. 定义 AIDL 接口文件3.2. 实现服务端&#xff08;Service&#xff09;3.3. 客户端绑定与调用 4. AIDL 的典型应用场景4.1. 多进程应用4.2. 与系统服务交互4.3. 高性能 IPC4.4. 跨应用…

PWM(脉宽调制)技术详解:从基础到应用实践示例

PWM&#xff08;脉宽调制&#xff09;技术详解&#xff1a;从基础到应用实践示例 目录 PWM&#xff08;脉宽调制&#xff09;技术详解&#xff1a;从基础到应用实践示例学前思考&#xff1a;一、PWM概述二、PWM的基本原理三、PWM的应用场景四、PWM的硬件配置与使用五、PWM的编程…

谷粒商城—分布式高级②.md

认证服务 1. 环境搭建 创建gulimall-auth-server模块,导依赖,引入login.html和reg.html,并把静态资源放到nginx的static目录下 2. 注册功能 (1) 验证码倒计时 //点击发送验证码按钮触发下面函数 $("#sendCode").click(function () {//如果有disabled,说明最近…

Nginx(详解以及如何使用)

目录 1. 什么是Nginx&#xff1f; 2. 为什么使用nginx? 3. 安装nginx 3.1?安装nginx的依赖插件 3.2 下载nginx ?3.3?创建一个目录作为nginx的安装路径 ?3.4?解压 ?3.5?进入解压后的目录 3.6?指定nginx的安装路径 ?3.7?编译和安装nginx 3.8 启动nginx ?…

STM32 HAL库标准库+ESP8266+机智云

前言 最近在项目中需要云平台对接&#xff0c;前面使用的是阿里云物理平台&#xff0c;具体开发可以看看我的这个文章&#xff1a;手把手教会使用阿里云平台&#xff0c;不过好像没有可以在手机很方便打开连接的&#xff0c;所以我在网上找到一些资料&#xff0c;发现机智云是…

【前端框架】Vue3 面试题深度解析

本文详细讲解了VUE3相关的面试题&#xff0c;从基础到进阶到高级&#xff0c;分别都有涉及&#xff0c;希望对你有所帮助&#xff01; 基础题目 1. 简述 Vue3 与 Vue2 相比有哪些主要变化&#xff1f; 答案&#xff1a; 响应式系统&#xff1a;Vue2 使用 Object.definePrope…

DarkLabel 2.4使用指南:高效标注视频数据目标检测标签

工具概述 DarkLabel 2.4 是一款强大的多功能标注工具&#xff0c;专为计算机视觉开发者设计&#xff0c;旨在提升标注工作的效率和精确度。其智能标注引擎支持两项核心功能&#xff1a;线性插值标注与多目标跟踪&#xff0c;极大地优化了视频标注过程。 &#xff08;1&#x…