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

基于面向对象和递归的拦截器设计模式

1 定义

拦截器模式(Interceptor Pattern),是指提供一种通用的扩展机制,可以在业务操作前后提供一些切面的(Cross-Cutting)的操作。这些切面操作通常是和业务无关的,比如日志记录、性能统计、安全控制、事务处理、异常处理和编码转换等。

在功能上,拦截器模式和面向切面编程(Aspect OrientedProgramming,AOP)的思想很相似。

推荐拦截器的实现方式的原因:

  1. 一个其命名更能表达前置处理和后置处理的含义。
  2. 拦截器的添加和删除会更加灵活。

2 设计原理

在这里插入图片描述

不同于Java的动态代理是利用Java反射机制的,拦截器模式完全是利用面向对象技术的,巧妙地使用组合模式外加递归调用实现了灵活、可扩展的前置处理和后置处理。

在拦截器模式中,主要包含以下角色:

  • TargetInvocation:包含了一组Interceptor和一个Target对象,确保在Target处理请求前后,按照定义顺序调用Interceptor做前置和后置处理。
  • Target:处理请求的目标接口。
  • Interceptor:拦截器接口。
  • InterceptorImpl:拦截器实现,用来在Target处理请求前后做切面处理。

各角色之间的关系如下类图所示:
在这里插入图片描述

编码实现

创建Target接口

public interface Target{ public Response execute(Request request); 
}

创建Interceptor接口

public interface Interceptor { public Response intercept(TargetInvocation targetInvocation); 
}

创建TargetInvocation


public class TargetInvocation {    private List<Interceptor> interceptorList = new ArrayList<>();    private Iterator<Interceptor> interceptors;    private Target target; private Request request;    public Response invoke(){        if( interceptors.hasNext() ){       //此处是整个算法的关键,这里会递归调用invoke()        Interceptor interceptor = interceptors.next();      interceptor.intercept(this);       }         return target.execute(request);     }     public void addInterceptor(Interceptor interceptor){         //添加新的Interceptor到TargetInvocation中         interceptorList.add(interceptor);         interceptors = interceptorList.iterator();     } 
}

创建具体的Interceptor

AuditInterceptor实现如下:

public class AuditInterceptor implements Interceptor{ @Override public Response intercept(TargetInvocation targetInvocation) {                                 if(targetInvocation.getTarget() == null) { throw new IllegalArgumentException("Target is null"); } System.out.println("Audit Succeeded "); return targetInvocation.invoke(); } 
}

LogInterceptor实现如下:

public class LogInterceptor implements Interceptor { @Override public Response intercept(TargetInvocation targetInvocation) { System.out.println("Logging Begin"); Response response = targetInvocation.invoke(); System.out.println("Logging End"); return response; }}

InterceptorDemo演示


public class InterceptorDemo { public static void main(String[] args) { TargetInvocation targetInvocation = new TargetInvocation(); targetInvocation.addInterceptor(new LogInterceptor()); targetInvocation.addInterceptor(new AuditInterceptor()); targetInvocation.setRequest(new Request()); targetInvocation.setTarget(request->{return new Response();});targetInvocation.invoke();}}

输出结果

Logging BeginAudit SucceededLogging End

小结

拦截器模式在开源框架中被广泛使用,例如,MVC框架Struts2的Interceptor机制正是使用该模式,只是在Struts2中Target叫Action,TargetInvocation叫ActionInvocation。在开源流程引擎Activity中也有使用该模式,其Target叫Command。在COLA框架中,同样使用拦截器模式来进行Command的前置和后置处理。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 1.24、定义浅层神经网络架构和算法(matlab)
  • Android11 framework 禁止三方应用开机自启动
  • 正则表达式在Python中的高级应用:从HTML中提取数据
  • c++应用网络编程之四Linux常用的网络IO模型
  • WPF之URI的使用
  • Linux 各目录
  • MySQL-显示所有错误信息
  • Linux——Shell脚本和Nginx反向代理服务器
  • MCU常见相关术语缩写说明
  • pnpm build打包时占内溢出
  • 【 DHT11 温湿度传感器】使用STC89C51读取发送到串口、通过时序图编写C语言
  • Python 二进制求和
  • 第五章:卷-将磁盘挂载到容器
  • linux环境交叉编译openssl库,以使Qt支持https
  • (二)原生js案例之数码时钟计时
  • [数据结构]链表的实现在PHP中
  • 【Leetcode】104. 二叉树的最大深度
  • 【编码】-360实习笔试编程题(二)-2016.03.29
  • 【从零开始安装kubernetes-1.7.3】2.flannel、docker以及Harbor的配置以及作用
  • 【个人向】《HTTP图解》阅后小结
  • Cookie 在前端中的实践
  • CSS中外联样式表代表的含义
  • Docker 笔记(2):Dockerfile
  • JavaWeb(学习笔记二)
  • Java应用性能调优
  • LeetCode18.四数之和 JavaScript
  • OpenStack安装流程(juno版)- 添加网络服务(neutron)- controller节点
  • Redis的resp协议
  • SAP云平台运行环境Cloud Foundry和Neo的区别
  • spring-boot List转Page
  • 初探 Vue 生命周期和钩子函数
  • 发布国内首个无服务器容器服务,运维效率从未如此高效
  • 诡异!React stopPropagation失灵
  • 机器人定位导航技术 激光SLAM与视觉SLAM谁更胜一筹?
  • 开源地图数据可视化库——mapnik
  • 如何优雅地使用 Sublime Text
  • 使用putty远程连接linux
  • 问题之ssh中Host key verification failed的解决
  • 在weex里面使用chart图表
  • MyCAT水平分库
  • RDS-Mysql 物理备份恢复到本地数据库上
  • ​TypeScript都不会用,也敢说会前端?
  • ​学习一下,什么是预包装食品?​
  • # Redis 入门到精通(九)-- 主从复制(1)
  • #NOIP 2014# day.1 生活大爆炸版 石头剪刀布
  • #多叉树深度遍历_结合深度学习的视频编码方法--帧内预测
  • (27)4.8 习题课
  • (C++)栈的链式存储结构(出栈、入栈、判空、遍历、销毁)(数据结构与算法)
  • (html5)在移动端input输入搜索项后 输入法下面为什么不想百度那样出现前往? 而我的出现的是换行...
  • (二)七种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB
  • (二)延时任务篇——通过redis的key监听,实现延迟任务实战
  • (七)c52学习之旅-中断
  • (三)Hyperledger Fabric 1.1安装部署-chaincode测试
  • (原創) 是否该学PetShop将Model和BLL分开? (.NET) (N-Tier) (PetShop) (OO)
  • (原創) 未来三学期想要修的课 (日記)