通过代理模式 + 责任链模式实现对目标执行方法拦截和增强功能

前言

         最近需要实现一个插件功能,但是如果做成两个接口的话(即执行前和执行后),那么会降低插件的可玩性,所以需做成类似AOP的环绕通知形式,所以就使用到了责任链模式和代理模式进行实现。

介绍

代理模式(Proxy Pattern)

        定义:由于某些原因需要给某对象提供一个代理以控制对该对象的访问。这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介。

        UML:

 

Java中,常见代理模式的实现有Java静态、动态代理,CGLIB动态代理,JAVAssist动态代理等等。

责任链模式(Chain of Responsibility Pattern)

       定义:为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。

在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。

        UML:

可以把它理解为一个链表,每个节点上的对象都实现了同一个接口,并且在对象内部指向下一个节点对象,在开始执行第一个节点的时候,就会传递到每一个节点

常见的责任链实现有 Servlet中的Filter,SpringMVC的Intercept拦截器,AOP中的环绕通知,Mybatis的插件功能,Druid中Filter等等。

实现

实现一个简单的目标执行器执行

定义一个Executor接口,TargetExecutor实现Executor并实现execute方法,然后通过Executor进行调用,定义一个参数对象,模拟真实业务场景。

现在需要通过代理和责任链实现对Executor的execute方法进行批量增强

定义一个封装代理对象

这个对象是用来在拦截器里面手动调用执行目标方法的,这样就可以在拦截前和拦截后做一些业务处理等等。

 

1:proceed():当调用Proceed对象的proceed方法时,即执行代理对象的目标方法

2:targetObject: 为真实的执行对象(这个是为了记录真实的目标执行对象,可以直接操作目标对象)

3:targetProxy: 为真实/代理对象(第一个拦截器为真实对象,后面的就是前一个拦截器的代理对象)

4:args: 目标执行对象调用方法的参数

定义一个责任链共用接口以及生成代理对象的共用方法

责任链中的共用实现接口

 

1:intercept():

       每个拦截器都需要实现的方法,参数为Proceed对象,每个具体的拦截器可根据具体逻辑进行操作真实的Executor对象和ParamEvent参数对象

2:newProxy():

       创建目标对象的代理方法,由于这里目标执行对象是使用接口实现的方式,所以使用的是JDK的动态代理,如果是普通的类,则可以使用CGLIB动态代理生成代理类

实现代理类的具体执行方法,进行对目标对象的增强

目标执行对象方法真实执行类,当目标执行对象调用目标执行方法时,需要调用拦截器的intercept方法,由拦截器手动调用proceed方法,进入下一个拦截器,因此形成调用链路。

 

1:targetObject: 具体目标执行对象

2:targetProxy:为真实/代理对象

3:intercept:下一个链路节点对象

4:invoke: 动态代理接口执行方法,该方法里面为调用拦截器得intercept方法

创建管理责任链链路对象

用于管理和创建目标执行对象的代理对象

 

1:interceptList:所有实现链路接口的对象有序集合

2:addIntercept():添加链路节点对象方法

3:createProxy(): 创建代理对象方法,参数为target(具体执行对象),利用循环创建代理对象将所有的拦截器生成一个责任链链路。

验证

记录execute方法的运行时间拦截器

修改目标执行方法的对象参数拦截器

修改目标执行对象属性值拦截器

 

  • 查看运行结果:

 

拦截器功能实现成功!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Javascript基础之-原型(prototype)

首先呢,prototype是对象里的一个内置属性,并且呢,这个属性是对于其他对象的一个引用。所以呢,思考下面的例子: var obj {a: 2 } var myObj Object.create(obj); console.log(myObj.a); // 2 console.log(myObj obj)…

Oracle查询今天、昨天、本周、上周、本月、上月数据

查询今天数据: SELECT COUNT(1) FROM T_CALL_RECORDS WHERE TO_CHAR(T_RKSJ,YYYY-MM-DD)TO_CHAR(SYSDATE,YYYY-MM-DD); 查询昨天数据: SELECT COUNT(1) FROM T_CALL_RECORDS WHERE TO_CHAR(T_RKSJ,YYYY-MM-DD)TO_CHAR(SYSDATE-1,YYYY-MM-DD)&…

usb一转多 树莓派zero_树莓派 Zero USB/以太网方式连接配置教程

树莓派 Zero 之所以成为一款非常棒的单板计算机并不全因为它小巧的尺寸和便宜的价格,还得益于它便捷、易用的特性。在加装了 Zero Quick Plug 或 microUSB/USB 转换头之后,将树莓派 Zero 和电脑连接起来。树莓派 Zero 即可配置成 USB/以太网设备&#xf…

vscode Go 1.11.4 编译错误 need Delve built by Go 1.11 or later

更新golang的版本为1.11.4之后vscode编译错误:executables built by Go 1.11 or later need Delve built by Go 1.11 or later 原因是delve的版本太老了,需要更新,且delve的github地址已经更换,很多教程里的地址是不对的 新地址安…

oppo的sd卡在哪里打开_oppo的sd卡在哪里打开

大家好,我是时间财富网智能客服时间君,上述问题将由我为大家进行解答。以oppo A91为例,其sd卡可直接在文件管理页面的存储里面即可打开。OPPO A91的屏幕为6.4英寸,主屏分辨率2400乘以1080像素,机身颜色有暗夜星辰&…

Navicat使用教程:使用Navicat Query Analyzer优化查询性能(第1部分)

下载Navicat Monitor最新版本Navicat Monitor 是一套安全、简单而且无代理的远程服务器监控工具。它具有强大的功能使你的监控发挥最大效用。受监控的服务器包括 MySQL、MariaDB 和 Percona Server,并与 Amazon RDS、Amazon Aurora、Oracle Cloud、Microsoft Azure …

dg oracle 切换模式_Oracle数据库 DGbroker三种保护模式的切换

1.三种保护模式– Maximum protection在Maximum protection下, 可以保证从库和主库数据完全一样,做到zero data loss.事务同时在主从两边提交完成,才算事务完成。如果从库宕机或者网络出现问题,主从库不能通讯,主库也立…

软件包管理

应用程序:程序:Architecture C语言:源代码-->(编译) 二进制格式脚本:解释器(二进制程序) 源代码-->编译-->链接-->运行程序:指令数据指令:芯片CP…

工业机器人码垛教学实施_工业机器人应用案例码垛详解

工业机器人应用案例码垛详解随着科技的进步以及现代化进程的加快,人们对搬运速度的要求越来越高,传统的人工码垛只能应用在物料轻便、尺寸和形状变化大、吞吐量小的场合,这已经远远不能满足工业的需求,机器人码垛机应运而生。机器…

第一家云创大数据产业学院在佛山职业技术学院挂牌

2019年1月10日,“云创大数据产业学院揭牌暨战略合作协议签署仪式”在佛山职业技术学院电子信息学院会议室举行。云创大数据总裁刘鹏教授、市场部经理单明月,佛山职业技术学院电子信息学院院长唐建生、副院长田钧、学院办公室主任赵雪章、信息工程系主任乔…

String与StringBuffer和StringBuilder的根本区别

*************************************优雅的分割线 ********************************** 分享一波:程序员赚外快-必看的巅峰干货 如果以上内容对你觉得有用,并想获取更多的赚钱方式和免费的技术教程 请关注微信公众号:HB荷包 一个能让你学习技术和赚钱方法的公众号,持续更…

16进制 ksh_AIX系统中如何统计进程打开的文件数目

作者:李烨楠 中国建设银行来自微信公众号:平台人生环境: AIX 6.1 AIX7.1前言:用户有时需要统计一个进程打开的文件数目,比如,在当前打开文件句柄使用量是否超过用户资源限制(/etc/security/limits)中 nofiles的取值时。那么&#…

前端Http协议缓存初解

[TOC] 简介 用户获取网络资源,需要通过非常长的网络去服务器上请求资源,另外服务端为了应对大量的用户请求而不断的提升硬件性能与带宽。这对用户与服务端都非常的不友好。而缓存就是为了解决用户请求速度与释放服务器压力而生的。 为什么我会写Http缓存&#xff0c…

详解java访问修饰符

*************************************优雅的分割线 ********************************** 分享一波:程序员赚外快-必看的巅峰干货 如果以上内容对你觉得有用,并想获取更多的赚钱方式和免费的技术教程 请关注微信公众号:HB荷包 一个能让你学习技术和赚钱方法的公众号,持续更…

educoder 二进制数据的位运算_二进制与位运算实用操作汇总(基础篇)

位运算是最高效而且占用内存最少的算法操作,但也是最难看懂的操作。然而,关于位运算的用法,笔者查了许多资料,似乎都没有找到详细而系统的讲解资料。笔者对位运算的操作相当感兴趣,因此斗胆尝试对位运算来一个的总结。…

企业为什么要做SEO,它的重要性有哪些?

对于SEO工作而言,我们知道一个网站做SEO的基础诉求就是让用户和搜索引擎更好的理解网站内容,虽然随着搜索引擎算法技术的迭代,目前SEO面临更大的挑战与竞争,但基于搜索营销,它目前仍然显得十分重要。 那么&#xff0…

白话说编程之java线程

白话说编程之java线程线程和进程:进程:线程:线程和进程的区别:详解多线程:并发为什么使用并发并发的执行原理并行线程的五种状态:创建状态:就绪状态:运行状态:阻塞状态:死…

powerdesigner显示工具面板_photoshop教程-画笔工具预设与选项设置

定义画笔预设在打开的“画笔”面板中,单击左侧的“画笔笔尖形状”名称,可显示笔尖形状图案。单击“画笔”面板左侧其他不同的选项名称,在右侧就会显示其对应的调节项。只单击不同选项前面的方框,可使此选项有效,但右侧…

C#属性的声明和使用演示源码片段

工作闲暇时间,将代码过程重要的一些代码做个收藏,如下代码是关于C#属性的声明和使用演示片段的代码,应该对码农有一些好处。 using System; class Person {private string myName "N/A";private int myAge 0;public string Name{g…

深入理解== 和 equals 的区别

深入理解 和 equals 的本质区别简介区别:图解:注意点:源码分析:总结分享一波:程序员赚外快-必看的巅峰干货简介 初学者常常被" “和‘equals ’所折磨,为什么,因为他们的大概意思相同,都是…