设计模式学习6——责任链模式及其在AOP在环绕通知中的应用

概述

讲了责任链模式的定义、简单使用和在AOP在环绕通知中的应用。

定义

在这里插入图片描述
简而言之就是,将问题交给自己的上级处理,由此形成一条链。

类图

在这里插入图片描述
类图主要包括Handler和具体Handler。
下面以报销的例子,实现责任链模式

部门报销

直接通过代码进行解释,部门报销如果在自己的可处理范围内,直接处理,否则移交上级处理。
责任链公共接口

public interface Handler {
    void setSuccessor(Handler handler);
    void handlerRequest(int money);
}

项目经理只能处理500以内的报销,否则移交部门经理处理。

public class DeptHandler implements Handler{
    private Handler successor;
    @Override
    public void setSuccessor(Handler handler) {
        this.successor=handler;
    }
    @Override
    public void handlerRequest(int money) {
        if(money<1000){
            System.out.println("部门经理批准"+money+"块");
            return;
        }
        if(successor!= null ){
            successor.handlerRequest(money);
        }
    }
}

部门经理只能处理1000以内的报销,否则移交总经理处理

public class GeneralHandler implements Handler{
    private Handler successor;
    @Override
    public void setSuccessor(Handler handler) {
        this.successor=handler;
    }
    @Override
    public void handlerRequest(int money) {
        System.out.println("总经理批准通过了"+money+"块");
    }
}

Client:

public class Client {
    public static void main(String[] args) {
        ProjectHandler projectHandler = new ProjectHandler();
        DeptHandler deptHandler = new DeptHandler();
        GeneralHandler generalHandler = new GeneralHandler();
        projectHandler.setSuccessor(deptHandler);
        deptHandler.setSuccessor(generalHandler);

        projectHandler.handlerRequest(100);
        System.out.println("=====");
        projectHandler.handlerRequest(600);
        System.out.println("=====");
        projectHandler.handlerRequest(1500);
    }
}

在这里插入图片描述
可以看到不同的要求交给了不同的部门处理,达成了责任链模式的需求,当然这里面可扩展的地方很多,不再赘述。

AOP环绕通知的责任链模式

首先说说AOP的执行流程:

  1. 将所有的注解转换成Advisor存在list中并排序。
  2. 将所有的通知都转换为环绕通知MethodInterceptor,用到了适配器模式。
  3. 然后创建并执行调用链对象MethodInvocation。
    下面就是演示调用链是如何执行的:
    先写两个通知类
   static class Advice1 implements MethodInterceptor {
        public Object invoke(MethodInvocation invocation) throws Throwable {
            System.out.println("Advice1.before()");
            Object result = invocation.proceed();// 调用下一个通知或目标
            System.out.println("Advice1.after()");
            return result;
        }
    }
    static class Advice2 implements MethodInterceptor {
        public Object invoke(MethodInvocation invocation) throws Throwable {
            System.out.println("Advice2.before()");
            Object result = invocation.proceed();// 调用下一个通知或目标
            System.out.println("Advice2.after()");
            return result;
        }
    }

自定义一个MethodInvocation,下面只保留部分必要代码

static class MyInvocation implements MethodInvocation{
        //目标
        private Object target;//1个目标
        //方法
        private java.lang.reflect.Method method;
        //参数列表
        private Object[] args;
        //通知集合
        List<MethodInterceptor> methodInterceptorList;//2个通知

        //当count=3的时候,结束调用
        //调用次数一开始是1
        private int count= 1;       
        @Override
        public Object proceed() throws Throwable {
            if(count>methodInterceptorList.size()){
                return method.invoke(target,args);
            }
            MethodInterceptor interceptor = methodInterceptorList.get(count++ - 1);
            return interceptor.invoke(this);
        }
}        

这里的调用链用的是递归的思想
count表示当前调用到哪里了。
下面来详细说明步骤,假设有当前有两个通知,也就是上面写的两个。

  1. count=1进来的时候
    count不是最后一个,跳过if,找到当前count对应的MethodInterceptor(Advice1),进入会执行Advice1的before,然后这里就体现递归的执行通知里的proceed。
  2. count=2
    count仍然不是最后一个,跳过if,继续根据count找到第二个MethodInterceptor(Advice2),执行Advice2的before,然后又进入proceed。
  3. count=3
    这时count>2,执行target的方法,执行完会返回执行Advice2中proceed后面的after2,再退回上一次执行after1。
    这就是执行链的执行思路
    在这里插入图片描述

应用

当要求按序执行的时候,一般会使用执行链
tomcat的过滤器和AOP通知的执行都是通过该模式执行。

参考

https://www.cnblogs.com/java-my-life/archive/2012/05/28/2516865.html
https://www.bilibili.com/video/BV1P44y1N7QG

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值