1.定义
一个对象在一条链上被多个拦截器拦截处理(当然,可能只会拦截,不会处理)的设计模式称为责任链模式。该模式是一个对象在多个角色中传递的过程。
类似于流程审批,申请单被级级审核。
2.构成
对象+拦截器
3.例子
由于责任链模式由多个拦截器组成,所以现在先让我们来撸3个拦截器:
/**
* 一号拦截器
*/
public class ResponsibilityInterceptor1 implements Interceptor {
/**
* 作用于真实对象之前的方法
* @param proxy 代理对象
* @param target 真实对象(被代理对象)
* @param method 方法对象
* @param args 方法参数
* @return 是否反射真实方法(true反射)
*/
@Override
public boolean before(Object proxy, Object target, Method method, Object[] args) {
System.out.print("我是一号拦截器的before");
return true;
}
/**
* 用于代理真实对象的方法(before返回false时触发)
* @param proxy 代理对象
* @param target 真实对象(被代理对象)
* @param method 方法对象
* @param args 方法参数
*/
@Override
public void around(Object proxy, Object target, Method method, Object[] args) {
System.out.print("我是一号拦截器的around");
}
/**
* 作用于真实对象方法之后的方法
* @param proxy 代理对象
* @param target 真实对象(被代理对象)
* @param method 方法对象
* @param args 方法参数
*/
@Override
public void after(Object proxy, Object target, Method method, Object[] args) {
System.out.print("我是一号拦截器的after");
}
}
/**
* 二号拦截器
*/
public class ResponsibilityInterceptor2 implements Interceptor {
/**
* 作用于真实对象之前的方法
* @param proxy 代理对象
* @param target 真实对象(被代理对象)
* @param method 方法对象
* @param args 方法参数
* @return 是否反射真实方法(true反射)
*/
@Override
public boolean before(Object proxy, Object target, Method method, Object[] args) {
System.out.print("我是二号拦截器的before");
return true;
}
/**
* 用于代理真实对象的方法(before返回false时触发)
* @param proxy 代理对象
* @param target 真实对象(被代理对象)
* @param method 方法对象
* @param args 方法参数
*/
@Override
public void around(Object proxy, Object target, Method method, Object[] args) {
System.out.print("我是二号拦截器的around");
}
/**
* 作用于真实对象方法之后的方法
* @param proxy 代理对象
* @param target 真实对象(被代理对象)
* @param method 方法对象
* @param args 方法参数
*/
@Override
public void after(Object proxy, Object target, Method method, Object[] args) {
System.out.print("我是二号拦截器的after");
}
}
/**
* 三号拦截器
*/
public class ResponsibilityInterceptor3 implements Interceptor {
/**
* 作用于真实对象之前的方法
* @param proxy 代理对象
* @param target 真实对象(被代理对象)
* @param method 方法对象
* @param args 方法参数
* @return 是否反射真实方法(true反射)
*/
@Override
public boolean before(Object proxy, Object target, Method method, Object[] args) {
System.out.print("我是三号拦截器的before");
return false;
}
/**
* 用于代理真实对象的方法(before返回false时触发)
* @param proxy 代理对象
* @param target 真实对象(被代理对象)
* @param method 方法对象
* @param args 方法参数
*/
@Override
public void around(Object proxy, Object target, Method method, Object[] args) {
System.out.print("我是三号拦截器的around");
}
/**
* 作用于真实对象方法之后的方法
* @param proxy 代理对象
* @param target 真实对象(被代理对象)
* @param method 方法对象
* @param args 方法参数
*/
@Override
public void after(Object proxy, Object target, Method method, Object[] args) {
System.out.print("我是三号拦截器的after");
}
}
然后借助jdk动态代理类进行代理,详情见动态代理文章。
最后,撸一个测试类:
@RunWith(SpringRunner.class)
@SpringBootTest
public class ResponsibilityTest {
/**
* 利用之前撸好的代理类进行多个拦截器的代理
*/
@Test
public void responsibilityTest(){
IProxyTest interceptor1 = (IProxyTest)InterceptorJdkProxy.bind(new ProxyTest(),"com.example.springredis.responsibility.ResponsibilityInterceptor1");
IProxyTest interceptor2 = (IProxyTest)InterceptorJdkProxy.bind(interceptor1,"com.example.springredis.responsibility.ResponsibilityInterceptor2");
IProxyTest interceptor3 = (IProxyTest)InterceptorJdkProxy.bind(interceptor2,"com.example.springredis.responsibility.ResponsibilityInterceptor3");
interceptor3.sayHello();
}
}
注:最初被代理的类为ProxyTest :
public class ProxyTest implements IProxyTest {
@Override
public void sayHello() {
System.out.print("说你好!");
}
}
测试类的运行结果为:
我是三号拦截器的before我是二号拦截器的before我是一号拦截器的before说你好!我是一号拦截器的after我是二号拦截器的after我是三号拦截器的after
由结果可以看出,每个拦截器的方法都被触发了,在拦截器的before方法被触发完了之后,触发了真实对象的方法,接着顺序触发了after方法。
interceptor3 为interceptor2 的代理对象,interceptor2 为interceptor1的代理对象,interceptor1为ProxyTest的代理对象。在interceptor3执行sayHello方法时,首先会进入jdk动态代理类的invoke方法:
/**
* 代理类实现逻辑,在代理类执行方法时,首先会进入该方法
* @param proxy 代理类对象
* @param method 方法对象
* @param args 方法传承
* @return 方法返回对象
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;//返回结果对象
//没有设置拦截器时,就直接反射方法
if(interceptorClass==null){
result = method.invoke(target,args);//通过反射调用真实对象方法
}
Interceptor interceptor = (Interceptor)Class.forName(interceptorClass).newInstance();//通过反射获取接口实例
if (interceptor.before(proxy,target,method,args)){
result = method.invoke(target,args);//通过反射调用真实对象方法
}else{
interceptor.around(proxy,target,method,args);
}
interceptor.after(proxy,target,method,args);
return result;
}
这个方法中会因为before方法放回true而反射被代理对象的sayHello方法,这个时候,就会换成interceptor2去调用sayHello方法,所以又会进入代理类,触发代理类的invoke方法,以此类推,知道调用ProxyTest(第一个代理类)的sayHello,接着顺序调用after。这就是责任链的整个流程。