责任链设计模式与应用:实现拦截器责任链统计接口执行时间和性能

本文介绍了责任链设计模式,包括其定义、使用场景和与策略模式的区别。通过代码实战展示了如何在Spring AOP中应用责任链模式,创建能够统计接口执行时间和性能的拦截器,涉及知识点包括拦截器实现、接口调用统计和顺序控制。
摘要由CSDN通过智能技术生成

一、什么是责任链设计模式

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())
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值