一、什么是责任链设计模式
1、什么是责任链设计模式?
责任链设计模式主要构成有抽象处理者、具体处理者、客户类,在处理请求的时候,将请求通过客户类发送至处理链路上,这样链路上所有处理对象都有机会处理请求,使发送者与接收者之间解耦。
见:https://blog.csdn.net/noaman_wgs/article/details/77838222
2、使用场景
使用责任链模式的优点:
- 发送者与接收方的处理对象类之间解耦;
- 封装每个处理对象,符合类的最小封装原则;
- 可以任意添加处理对象,调整处理对象之间的顺序,提高了维护性和可拓展性;
使用场景:
当请求到来时,不知道由哪个具体对象去处理或者每个对象都需要处理请求的时候,可以使用责任链模式。比如在OA系统中,当员工发起一个流程的时候,需要经过HR-组长-部门老大-公司老总等审批的时候,就可以使用责任链模式,不同的处理对象(HR-组长-部门老大-公司老总)使用不同的封装类组装成一个处理链路,使用这个处理链路去处理员工发起的请求。
3、责任链模式与策略模式的区别
策略模式和责任链模式很像,都是有多个处理对象去处理同一个请求。
不同之处在于对于同一个请求,策略模式可以经过选择使用具体的策略类处理请求;而责任链模式不能根据请求判断使用哪个处理类处理请求,需要链路上的处理类全部处理一遍请求才能得出结果。
二、代码实战
代码:https://github.com/nomico271/inspire-demo/tree/master/Ch1_ExecutorChainPattern
下面将结合Spring AOP知识,应用责任链设计模式,设计一个能够打印调用接口的参数、统计执行时间、执行次数的拦截器。
用到的知识点有:
- 框架:Spring Boot
- 设计模式:责任链设计模式
- Spring AOP
- 反射
- 注解
项目结构:
示意图如下:
下面看下代码实现。
1、拦截器责任链的实现
(1)首先定义拦截器抽象:可以定义拦截器的顺序、方法执行前的逻辑和方法执行完的逻辑,见InspireInterceptor.java;
(2)实现自定义功能的具体拦截器的实现,如打印接口入参信息的拦截器、统计接口调用执行时间的拦截器、统计接口调用次数的拦截器等等,见:
- CostTimeInterceptor.java
- LoggerInterceptor.java
- MethodCountInterceptor.java
(3)拦截器客户端,构建拦截器执行链并进行排序,之后按顺序执行拦截器链路中拦截器的before和after方法,见InspireInterceptorChainClient.java
对责任链进行排序的代码如下:
@PostConstruct
public void loadInterceptors() {
if (!CollectionUtils.isEmpty(interceptorList)) {
for (InspireInterceptor interceptor : interceptorList) {
interceptor.setOrder(resolveOrder(interceptor));
}
Collections.sort(interceptorList, (o1, o2) -> o1.getOrder() - o2.getOrder());
}
}
/**
* 获取拦截器注解中定义的优先级
*
* @param interceptor
* @return
*/
private int resolveOrder(InspireInterceptor interceptor) {
if (!interceptor.getClass().isAnnotationPresent(InterceptorOrder.class)) {
return InterceptorOrder.LOWEST_ORDER;
} else {
return interceptor.getClass().getAnnotation(InterceptorOrder.class).order();
}
}
(4)另:在拦截器执行过程中,可以自定义拦截器执行顺序,见注解@InterceptorOrder;
同时,需要有个上下文保存调用的方法获取接口入参等信息,以便能够在多个拦截器中传递,见:InspireContext、InspireRequest、InspireResponse、TheadLocalHolder
完整代码如下:
// 注解类, 定义拦截器顺序
@Retention(RetentionPolicy.RUNTIME)
@Target({
ElementType.TYPE})
@Documented
public @interface InterceptorOrder {
/**
* 优先级, 值越小, 优先级越高
*
* @return
*/
int order() default LOWEST_ORDER ;
int LOWEST_ORDER = Integer.MAX_VALUE;
int HIGHEST_ORDER = Integer.MIN_VALUE;
}
// 拦截器
public abstract class InspireInterceptor {
private int order;
public int getOrder() {
return order;
}
public void setOrder(int order) {
this.order = order;
}
public boolean executeBefore(InspireContext context) {
return true;
}
public void executeAfter(InspireContext context) {
}
}
// 拦截器实现1: 打印接口调用参数
@Slf4j
@Component
@InterceptorOrder(order = 10)
public class LoggerInterceptor extends InspireInterceptor {
@Override
public boolean executeBefore(InspireContext context) {
return super.executeBefore(context);
}
@Override
public void executeAfter(InspireContext context) {
String method = context.getRequest().getMethod();
Map<String, Object> paramsMap = context.getRequest().getParamsMap();
log.info("invoke [method:{}] start, params:{}", method, paramsMap.toString())