当前位置: 首页 > news >正文

同一个框架里的两种拦截器——注解驱动vs数据库驱动

同一个框架里的两种拦截器——注解驱动 vs 数据库驱动

文章目录

  • 同一个框架里的两种拦截器——注解驱动 vs 数据库驱动
    • 一、同一个模式,两种实现
    • 二、第二套拦截器:流程任务级的环绕式拦截
    • 三、一个升级版:异步分流
    • 四、两套拦截器放一起看
    • 五、为什么流程级用数据库而不是注解
    • 六、接口设计:before 和 after 为什么分开
    • 七、passProcess 拦截器 vs doProxy 拦截链:一个上午10点的场景
    • 八、结语

一、同一个模式,两种实现

之前写过责任链拦截器——doProxy读注解拼链,transInterceptorlogInterceptormonitorInterceptor三个节点串成一条链。那是方法级的,控制粒度是"这个方法需不需要事务、日志、监控"。

但在同一个框架里,还有另一套拦截器。它们不是面向方法,而是面向流程任务节点。这套拦截器在ProcessService.passProcess里,工作方式完全不同。

两套拦截器放在一起看,才是完整的横切关注点解决方案。

二、第二套拦截器:流程任务级的环绕式拦截

passProcess是工作流审批通过的核心方法。每个流程节点的审核人点"通过"时,走这个方法:

passProcess(taskid): ├── claim(taskid) // 拾取任务 ├── 从DB查拦截器配置 // 根据流程定义+任务节点查表 ├── 循环 before 列表 → beforeTrans() // 前置拦截 ├── 保存表单数据 + 提交流程 // 核心业务 └── 循环 after 列表 → afterTrans() // 后置拦截

核心代码:

// 获取任务拦截器——从数据库查task_interceptor intercptorobj=this.getinterceptor(taskid);Stringbeforeid=null,afterid=null;if(intercptorobj!=null){beforeid=intercptorobj.getBeforeId();// 前置拦截器ID列表afterid=intercptorobj.getAfterId();// 后置拦截器ID列表}// 执行前置拦截器if(beforeid!=null&&!"".equals(beforeid)){String[]beforeids=beforeid.split(",");for(inti=0;i<beforeids.length;i++){before beforeobj=(before)BeanFactory.getBean(beforeids[i]);beforeobj.beforeTrans(center);}}// ... 保存表单 + 提交流程 ...// 执行后置拦截器if(afterid!=null&&!"".equals(afterid)){String[]afterids=afterid.split(",");for(inti=0;i<afterids.length;i++){after afterobj=(after)BeanFactory.getBean(afterids[i]);afterobj.afterTrans(center);}}

这套拦截器有几个特点:

配置放在数据库里task_interceptor表存储了流程定义Key、任务节点Key、前置拦截器ID列表、后置拦截器ID列表。修改一个节点要不要加拦截器,改一行记录就行,代码不用动。

调用方式是顺序循环。不是责任链的"串一串",而是最简单的 for 循环——先跑完所有前置,再跑业务,再跑完所有后置。这样做的好处是:前置之间彼此独立,一个拦截器失败不会影响后续拦截器的调用。

beforeafter是两个分离的接口。它们不是同一个接口的不同方法,而是两个完全独立的接口。这意味着——同一个节点可以只配前置不配后置,反之亦然。比如"社会保险关系转出"节点的 after 里配一个"同步到税务系统",但不需要前置拦截。

三、一个升级版:异步分流

passProcessHK里,after 拦截器还做了一个精妙的分流:

for(inti=0;i<afterids.length;i++){after afterobj=(after)BeanFactory.getBean(afterids[i]);if(isSpecific(intercptorobj.getTaskDefKey(),afterids[i])){// 特定节点+特定拦截器 → 异步线程execTax exec=newexecTax(afterobj,center);newThread(exec).start();}else{// 普通情况 → 同步执行afterobj.afterTrans(center);}}

这里引入了一个isSpecific判断——查询configSpecificDao表,看当前节点是否配置了某个 after 拦截器的特殊处理。比如"同步税务"这个操作,在大部分节点是同步执行(流程必须等税务确认才能往下走),但在某些只读节点可以异步执行(后台慢慢推,不影响审批人点通过)。

同一个拦截器,同样的 after 接口,在 A 节点走同步、在 B 节点走异步——这不是代码决定的,是数据库里的configSpecificDao表决定的。

这就是数据库驱动配置的威力:拦截策略的变更不需要重新编译、不需要重启服务,改一条SQL就上线。

四、两套拦截器放一起看

doProxy 拦截链passProcess 拦截器
粒度方法级(同一个类的所有方法)流程任务级(某个流程的某个节点)
配置方式注解@Trans@Logger@monitoring数据库task_interceptor
调用模式责任链(trans→log→monitor→invoke)顺序循环(逐个调 before/after)
拦截器接口统一的Interceptor.invoke()分离的before.beforeTrans()+after.afterTrans()
顺序控制链的拼装顺序决定执行顺序循环顺序即执行顺序
变更成本改代码、编译、部署改数据库一行记录
适用场景通用基础设施(事务、日志、监控)业务级横切(数据同步、消息推送、权限检查)

这不是两套独立的方案,而是同一个模式在不同粒度的两种表现

  • 方法级用注解,因为"这个方法要不要事务"是框架能力,跟具体业务逻辑无关
  • 流程级用数据库,因为"审批通过后要不要同步税务"是业务能力,跟具体流程设计有关

五、为什么流程级用数据库而不是注解

一个很自然的问题是:passProcess里的拦截器,为什么不像doProxy一样用注解?在 ProcessService 的方法上加@Before("taxSync")@After("pushMessage")不就行了吗?

不行。因为同一个passProcess方法处理所有流程的所有节点。审批请假、报销、资产申购、合同签批——几百个流程、几千个节点,都走过同一个passProcess方法。你在方法上加@Before,那就是对所有流程生效,做不到"只在社保关系转移的审批节点触发同步税务"。

数据库驱动的拦截器解决了这个问题:绑定的单位不是方法,而是 (流程定义Key, 任务节点Key) 的组合

-- task_interceptor 表结构(简化)key|taskDefKey|beforeid|afterid-------------|--------------|---------------|------------social_trans|hr_approve|checkLimit|notifySMS social_trans|finance_pay|validateFund|syncTax,pushMessage leave_apply|manager_ok||notifySMS

同一个passProcess执行到social_trans流程的finance_pay节点时,触发validateFund前置 +syncTaxpushMessage后置。执行到leave_apply流程的manager_ok节点时,只触发notifySMS后置。

这就是数据库配置的本质:把"在哪里触发什么"从代码中抽出来,变成数据。

六、接口设计:before 和 after 为什么分开

doProxy 的链式拦截器只有一个Interceptor接口。passProcess 却拆成了两个:

publicinterfacebefore{voidbeforeTrans(DataCentercenter);}publicinterfaceafter{voidafterTrans(DataCentercenter);}

为什么要分开?

因为前置和后置的责任边界不同。前置拦截器可以拒绝执行——比如checkLimit发现预算超了,抛异常,流程中止,用户看到错误提示。后置拦截器不应该拒绝执行——审批已经通过了,syncTax同步失败应该重试,不应该让用户收到"审批失败了但其实是同步税务报错"这种混淆信息。

更实际的是:很多业务场景只需要后置不需要前置(比如审批通过后发短信通知),或者只需要前置不需要后置(比如审批前校验数据完整性)。拆成两个接口,数据库里配一个字段就行,不需要配了之后在代码里判断beforeId为空时跳过。

七、passProcess 拦截器 vs doProxy 拦截链:一个上午10点的场景

假设一个社保局的审批人员在上午10点通过了某人的"社保关系转移"申请。

doProxy 链做的事(通用基础设施):

  • transInterceptor:开启事务
  • logInterceptor:记录"调用 passProcess,insid=XX"
  • monitorInterceptor:开始计时

passProcess 拦截器做的事(业务流程切面):

  • before:validateTransfer→ 校验是否符合转出条件
  • before:checkArrears→ 检查是否欠费
  • 业务:保存表单、完成任务、流转到下一个节点
  • after:syncNationalPlatform→ 同步到国家医保平台
  • after:sendSMS→ 给申请人发"已受理"短信

两套拦截器的分工是明确的

  • doProxy 管的是"这个代码执行得对不对"——事务、日志、监控
  • passProcess 管的是"这个业务发生时要联动什么"——校验、同步、通知

八、结语

同一个框架里有两种拦截器实现,不是设计冗余,是粒度需求不同

方法级需求(“所有方法都需要事务”)用注解,因为它是编译时就确定的通用规则。流程级需求(“社保转移审批通过时要同步税务”)用数据库,因为它是随政策变化而变化的业务规则。

两套拦截器的接口设计也不同——方法级用统一的Interceptor接口做责任链,流程级拆成beforeafter做环绕式。这不是谁更优雅的问题,是每个粒度需要什么样的控制方式

最重要的是这个认知:拦截器不只有一种实现方式。注解驱动的、责任链串接的、CGLIB 代理的——这些是互联网后端的主流答案。但政务系统里,真正需要灵活变更的是业务流程级别的横切逻辑,数据库驱动反而更合适。改一行记录就上线,不需要走编译部署流程。

知道什么时候该用哪种——这比会用其中任何一种都重要。

http://www.jsqmd.com/news/1055161/

相关文章:

  • 终极Forza Mods AIO完整指南:免费解锁极限竞速地平线4/5无限可能
  • 收藏必备|2026全年格拉苏蒂售后网点权威核验报告,全国60余家正规维修门店详细地址公开 - 亨得利腕表服务中心
  • 2026年6月最新萧邦中国官方售后服务热线网点客服电话地址 - 亨得利官方服务中心
  • RimSort模组管理全攻略:从新手到高手的进阶路线图 [特殊字符]
  • i.MX 6SoloX接口时序设计:从参数到PCB的硬件工程实践
  • 重磅发布|2026年6月百达翡丽官方售后网点全面核验专项报告,官方维修服务网点全新营业地址投入运营 - 百达翡丽中国服务中心
  • 基于海天4S选股标准,批量遍历全市场个股,自动输出初选合格股票清单。
  • i.MX 6电源与电气特性设计:从芯片手册到硬件实战避坑指南
  • 微信小程序wxapkg文件解密与解包技术详解:从原理到实践
  • 宜昌销量好的贴汽车膜、贴隐形车衣、车窗膜哪家好,膜一姐售后好不好?品牌对比与选购指南 - 汽车新知百晓生
  • 2026 年 6 月爱彼维修服务中心实地核查 60 + 网点更新 - 亨得利腕表服务中心
  • 打工人如何将DeepSeek-V4嵌入VSCode实现日省2.7小时
  • 5分钟免费搞定抖音视频下载:douyin-downloader终极完整指南
  • 2026格拉苏蒂全国售后网络布局优化完成!60余家官方服务门店详细地址、官方咨询电话完整汇总整理 - 亨得利腕表服务中心
  • 2006考研数二真题(冲刺速通版)
  • i.MX 6SoloX引脚配置与BGA封装设计实战指南
  • MEMS加速度计PCB布局与焊接工艺详解:以NXP FXLS8964AF为例
  • 2026芜湖市家里卫生间漏水、阳台漏水、楼顶漏水、阳台漏水、地下室渗水、阳光房漏水各种房屋漏水情况不用愁!本地防水补漏公司为您排忧解难!精准推荐附近专业防水团队 - 伶鹿到家
  • 4S体系择时模块代码实现,根据指数估值分位,判定当前整体仓位档位。
  • 构建企业级用户代理管理架构:UserAgent-Switcher远程配置部署指南
  • i.MX 6SoloX引脚配置实战:从封装选型到PCB布局与软件配置
  • 2026年6月最新萧邦中国官方售后客服地址服务热线网点电话 - 亨得利官方服务中心
  • Mate Engine:免费开源虚拟桌面伴侣终极指南 - 打造你的专属二次元伙伴
  • 2026年6月百达翡丽官方售后升级,全国各城市官方维修网点最新地址与咨询热线完整查询 - 百达翡丽中国服务中心
  • Termux+Qwen手机端离线翻译实战指南
  • 从Word到LaTeX的终极免费转换:docx2tex三步快速上手指南
  • 抖音口碑优质公会推荐 - 舒雯文化
  • 嵌入式开发实战:MCU选型、Freescale文档解读与CodeWarrior工具链应用
  • 国内合规调用Gemini 3.1Pro:本地代理+标准化API实战指南
  • 百达翡丽售后全新布局:2026年6月全国官方腕表维修服务更新升级,售后网点全新营业地址正式运营 - 百达翡丽中国服务中心