概述
讲了责任链模式的定义、简单使用和在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的执行流程:
- 将所有的注解转换成Advisor存在list中并排序。
- 将所有的通知都转换为环绕通知MethodInterceptor,用到了适配器模式。
- 然后创建并执行调用链对象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表示当前调用到哪里了。
下面来详细说明步骤,假设有当前有两个通知,也就是上面写的两个。
- count=1进来的时候
count不是最后一个,跳过if,找到当前count对应的MethodInterceptor(Advice1),进入会执行Advice1的before,然后这里就体现递归的执行通知里的proceed。 - count=2
count仍然不是最后一个,跳过if,继续根据count找到第二个MethodInterceptor(Advice2),执行Advice2的before,然后又进入proceed。 - 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