java 责任链模式的三种实现
责任链模式
责任链模式的定义:使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系, 将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理他为止。这里就不再过多的介绍什么是责任链模式,主要来说说java中如何编写。主要从下面3个框架中的代码中介绍。
- servlet中的filter
- dubbo中的filter
- mybatis中的plugin 这3个框架在实现责任链方式不尽相同。
servlet中的Filter
servlet中分别定义了一个 Filter和FilterChain的接口,核心代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
public final class ApplicationFilterChain implements FilterChain { private int pos = 0 ; //当前执行filter的offset private int n; //当前filter的数量 private ApplicationFilterConfig[] filters; //filter配置类,通过getFilter()方法获取Filter private Servlet servlet @Override public void doFilter(ServletRequest request, ServletResponse response) { if (pos < n) { ApplicationFilterConfig filterConfig = filters[pos++]; Filter filter = filterConfig.getFilter(); filter.doFilter(request, response, this ); } else { // filter都处理完毕后,执行servlet servlet.service(request, response); } } } |
代码还算简单,结构也比较清晰,定义一个Chain,里面包含了Filter列表和servlet,达到在调用真正servlet之前进行各种filter逻辑。
Dubbo中的Filter
Dubbo在创建Filter的时候是另外一个方法,通过把Filter封装成 Invoker的匿名类,通过链表这样的数据结构来完成责任链,核心代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
private static <T> Invoker<T> buildInvokerChain( final Invoker<T> invoker, String key, String group) { Invoker<T> last = invoker; //只获取满足条件的Filter List<Filter> filters = ExtensionLoader.getExtensionLoader(Filter. class ).getActivateExtension(invoker.getUrl(), key, group); if (filters.size() > 0 ) { for ( int i = filters.size() - 1 ; i >= 0 ; i --) { final Filter filter = filters.get(i); final Invoker<T> next = last; last = new Invoker<T>() { ... public Result invoke(Invocation invocation) throws RpcException { return filter.invoke(next, invocation); } ... }; } } return last; } |
Dubbo的责任链就没有类似FilterChain这样的类吧Filter和调用Invoker结合起来,而是通过创建一个链表,调用的时候我们只知道第一个节点,每个节点包含了下一个调用的节点信息。 这里的虽然Invoker封装Filter没有显示的指定next,但是通过java匿名类和final的机制达到同样的效果。
Mybatis中的Plugin
Mybatis可以配置各种Plugin,无论是官方提供的还是自己定义的,Plugin和Filter类似,就在执行Sql语句的时候做一些操作。Mybatis的责任链则是通过动态代理的方式,使用Plugin代理实际的Executor类。(这里实际还使用了组合模式,因为Plugin可以嵌套代理),核心代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
public class Plugin implements InvocationHandler{ private Object target; private Interceptor interceptor; @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (满足代理条件) { return interceptor.intercept( new Invocation(target, method, args)); } return method.invoke(target, args); } //对传入的对象进行代理,可能是实际的Executor类,也可能是Plugin代理类 public static Object wrap(Object target, Interceptor interceptor) { Class<?> type = target.getClass(); Class<?>[] interfaces = getAllInterfaces(type, signatureMap); if (interfaces.length > 0 ) { return Proxy.newProxyInstance( type.getClassLoader(), interfaces, new Plugin(target, interceptor, signatureMap)); } return target; } } |
简单的示意图如下:
总结
这里简单介绍了Servlet、Dubbo、Mybatis对责任链模式的不同实现手段,其中Servlet是相对比较清晰,又易于实现的方式,而Dubbo和Mybatis则适合在原有代码基础上,增加责任链模式代码改动量最小的。
上面是转发别人的。
下面是个人的模拟实现
1.web filter中的过滤器很多人都了解,所以不做模拟
2.dubbo中filter
public void test() {
List<Filter> lists = new ArrayList<>();
lists.add(new SayWorldFilter());
lists.add(new SayHelloFilter()); Request request = new MyRequest(); for (Filter filter : lists) {
Request next = request;
request = new Request() {
@Override
public String test() {
return filter.filter(next);
}
};
}
request.test();
}
3.mybatis 中使用动态代理生产的包装类实现过滤
Request request = (Request) (RequestWrap.wrap(new MyRequest(), new SayWorldFilter()));
request = (Request) (RequestWrap.wrap(request, new SayHelloFilter()));
request.test();
具体代码见附件。
https://files.cnblogs.com/files/z-test/filter.rar
java 责任链模式的三种实现的更多相关文章
- java责任链模式及项目实际运用
1.前言 上次我们认识了java责任链模式的设计,那么接下来将给大家展示责任链模式项目中的实际运用.如何快速搭建责任链模式的项目中运用. 2.简单技术准备 我们要在项目中使用借助这样的几个知识的组合运 ...
- Java责任链模式
责任链模式 顾名思义,责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链.这种模式给予请求的类型,对请求的发送者和接收者进行解耦.这种类型的设计 ...
- Java设计模式系列之责任链模式
责任链模式 责任链模式是一种对象的行为模式.在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链.请求在这个链上传递,直到链上的某一个对象决定处理此请求.发出这个请求的客户端并不知道 ...
- 详解java设计模式之责任链模式
详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt175 从击鼓传花谈起 击鼓传花是一种热闹而又紧张的饮酒游戏.在酒宴上宾客依次 ...
- Java模式开发之责任链模式
Java模式开发之责任链模式 从击鼓传花谈起 击鼓传花是一种热闹而又紧张的饮酒游戏.在酒宴上宾客依次坐定位置,由一人击鼓.击鼓的地方与传花的地方是分开的.以示公正. 開始击鼓时,花束就開始依次传递,鼓 ...
- Java描述设计模式(15):责任链模式
本文源码:GitHub·点这里 || GitEE·点这里 一.生活场景描述 1.请假审批流程 公司常见的请假审批流程:请假天数 当 day<=3 天,项目经理审批 当 3<day<= ...
- 责任链模式Scala的7种实现
责任链模式是经典的GoF 23种设计模式之一,也许你已经了解这种模式.不管你是否熟悉,建议读者在阅读本文之前,不妨先思考下面三个问题: (1) 如何用多种风格迥异的编程范式来实现责任链模式? (2) ...
- 浅谈Java五大设计原则之责任链模式
首先我们得先定义一个责任链模式: 责任链模式是一种线性执行流程,多个对象都有机会去执行同一个任务,只是在执行过程中, 由于执行的权利和范围不一样,那么当自己不能处理此任务时,就必须将这个任务抛给下一个 ...
- JAVA设计模式之责任链模式
在阎宏博士的<JAVA与模式>一书中开头是这样描述责任链(Chain of Responsibility)模式的: 责任链模式是一种对象的行为模式.在责任链模式里,很多对象由每一个对象对其 ...
随机推荐
- 第三十九篇 入门机器学习——Numpy.array的基础操作——合并与分割向量和矩阵
No.1. 初始化状态 No.2. 合并多个向量为一个向量 No.3. 合并多个矩阵为一个矩阵 No.4. 借助vstack和hstack实现矩阵与向量的快速合并.或多个矩阵快速合并 No.5. 分割 ...
- rancher2中文文档地址
rancher2中文文档地址 待办 https://docs.rancher.cn/
- Coloring Colorfully
问题 C: Coloring Colorfully 时间限制: 1 Sec 内存限制: 128 MB[提交] [状态] 题目描述 N块瓦片从左到右排成一行.每个块的初始颜色由长度为N的字符串S表示. ...
- ansible笔记(2):管理清单配置详解
前情提要:管理清单(Iventory)配置文件/etc/ansible/hosts.通过修改该配置文件以达到管理受控主机的目的. 在我的实验平台上有3台主机:192.168.232.181(an ...
- CSS input
去除激活 input 的默认边框 // 三种方法都能实现 input{ outline: none; outline: medium; outline:; } 修改光标颜色 input{ outl ...
- 情人节用Python智能聊天机器人的实现|制作一个虚拟恋人
首先项目需要的包 import urllib.request import urllib.parse from tkinter import * import time PS:另外很多人在学习Pyth ...
- MyBatis(6)——分页的实现
分页的实现 a)通过mysql的分页查询语句: 说明:sql的分页语句格式为select * from aaa limit #{startIndex},#{pageSize} //---------- ...
- opencv:联通组件扫描
#include <opencv2/opencv.hpp> #include <iostream> using namespace cv; using namespace st ...
- Mysql查看连接数(连接总数、活跃数、最大并发数)
show variables like '%max_connection%'; set global max_connections=1000;
- hadoop3 配置second name node
设置hdfs-site.xml <property> <name>dfs.http.address</name> <value>192.168.1.81 ...