目录
?1.拦截器
?1.1在JDK代理中使用拦截器:
2.责任链模式
?2.1定义责任链拦截器接口
由于动态代理一般都比较难理解,程序设计者会设计一个拦截器接口供开发者使用,开发者只要知道拦截器接口的方法、含义和作用即可,无须知道动态代理是怎么实现的。用JDK动态代理来实现一个拦截器的逻辑,为此先定义拦截器接口Interceptor
?1.拦截器
package service;
import java.lang.reflect.Method;
public interface Interceptor {
boolean before(Object proxy, Object target, Method method,Object []args);
void around(Object proxy, Object target, Method method,Object []args);
void after(Object proxy, Object target, Method method,Object []args);
}
这里定义了3个方法,before、around、after方法,分别给予这些方法如下逻辑定义。
- 3个方法的参数为:proxy代理对象、target真实对象、method方法、args运行方法参数?
- before方法返回boolean值,它在真实对象前调用。当返回为true时,则反射真实对象的方法;当返回为false时,则调用around方法。
- 在反射真实对象方法或者around方法执行之后,调用after方法。
?实现类代码:
package service.serviceimpl;
import service.Interceptor;
import java.lang.reflect.Method;
public class MyInterceptor implements Interceptor {
@Override
public boolean before(Object proxy, Object target, Method method, Object[] args) {
System.out.println("反射方法前逻辑");
return false;//不调用真实对象方法,为true调用
}
@Override
public void around(Object proxy, Object target, Method method, Object[] args) {
System.out.println("反射方法逻辑");//before为false调用
}
@Override
public void after(Object proxy, Object target, Method method, Object[] args) {
System.out.println("取代了真实对象方法");
}
}
?1.1在JDK代理中使用拦截器:
package classtext;
import service.Interceptor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class InterceptorJdkProxy implements InvocationHandler {
Object target=null;//真实对象
String interceptorClass=null;//拦截器全类名
public InterceptorJdkProxy(Object target,
String interceptorClass){
this.target=target;
this.interceptorClass=interceptorClass;
}
/**
* 绑定真实对象,返回代理对象
* @param target
* @param interceptorClass
* @return
*/
public static Object bind(Object target, String interceptorClass){
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InterceptorJdkProxy(target, interceptorClass));
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
if (interceptorClass==null){//如果使用拦截器则返回真实对象之后结束
return method.invoke(target,args);
}
Object result=null;
//通过反射生成拦截器
Interceptor interceptor=(Interceptor) Class.forName(interceptorClass).newInstance();
if (interceptor.before(proxy,target,method,args)){
result=method.invoke(proxy,args);//为true返回真实对象方法结束,
}else {//否则执行around方法
interceptor.around(proxy,target,method,args);
}//调用after方法
interceptor.after(proxy,target,method,args);
return result;
}
}
不明白方法参数看这篇:(2条消息) 一文搞懂两种最常用的动态代理:JDK和CGLIB_m0_56058975的博客-CSDN博客
流程图如下:
?
?开启测试:
package test;
import classtext.InterceptorJdkProxy;
import service.HelloWordService;
import service.serviceimpl.HelloWordServiceImpl;
public class InterceptorJdkProxyTest {
public static void main(String[] args) {
HelloWordService proxy=(HelloWordService)InterceptorJdkProxy.bind(new HelloWordServiceImpl()
,"service.serviceimpl.MyInterceptor");
proxy.sayHello();
}
}
运行结果如下:
反射方法前逻辑
反射方法逻辑
取代了真实对象方法
2.责任链模式
责任链模式可以理解为拦截器的升级版,举个例子:一个员工需要请假一周,如果把请假申请单看成一个对象,那么它需要经过项目经理、部门经理、人事等多个角色的审批,每个角色都有机会通过拦截这个申请单进行审批或者修改。这个时就要考虑提供项目经理、部门经理和人事的处理逻辑,所以需要提供3个拦截器,而传递的则是请假申请单
如图所示:
?
?当一个对象在一条链上被多个拦截器处理就被称为责任链模式(拦截器可以选择拦截或者不拦截),它用于一个对象在多个角色中传递的场景。还是刚才的例子,申请单走到项目经理那,经理可能把申请时间“一周”改为“5天”,从而影响了后面的审批,后面的审批都要根据前面的结果进行。这个时候可以考虑用层层代理来实现,就是当申请单(target)走到项目经理处,使用第一个动态代理proxy1。当它走到部门经理处,部门经理会得到一个在项目经理的代理 proxy1基础上生成的 proxy2来处理部门经理的逻辑。当它走到人事处,会在proxy2的基础生成proxy3。如果还有其他角色,依此类推即可。
?2.1定义责任链拦截器接口
public class Interceptorl implements Interceptor
public boolean before(Object proxy, Object target, Method method, Object [ ]
args)
System.out.println("【拦截器1】的before方法");
return true;
public void around(Object proxy, object target, Method method, object[]
args)
System.out.println("【拦截器1】的aroud方法");
public void after(Object proxy, object target, Method method, object[]
args)
System.out.println("【拦截器1】的after方法");
------
public class Interceptorl implements Interceptor
public boolean before(Object proxy, Object target, Method method, Object [ ]
args)
System.out.println("【拦截器2】的before方法");
return true;
public void around(Object proxy, object target, Method method, object[]
args)
System.out.println("【拦截器2】的aroud方法");
public void after(Object proxy, object target, Method method, object[]
args)
System.out.println("【拦截器2】的after方法");
-------------
public class Interceptorl implements Interceptor
public boolean before(Object proxy, Object target, Method method, Object [ ]
args)
System.out.println("【拦截器3】的before方法");
return true;
public void around(Object proxy, object target, Method method, object[]
args)
System.out.println("【拦截器3】的aroud方法");
public void after(Object proxy, object target, Method method, object[]
args)
System.out.println("【拦截器3】的after方法");
?单元测试:
public static void main(String[] args)
Helloworld proxyl = (HelloWorld) InterceptorJdkProxy.bind(
new
HelloWorldImpl(), "service.serviceimpl.Interceptor1");
Helloworld proxy2 =
(Helloworld) InterceptorJdkProxy.bind(
proxy1, "service.serviceimpl.Interceptor2");
Helloworld proxy3 = (Helloworld) InterceptorJdkProxy.bind(
proxy2, "service.serviceimpl.Interceptor3");
proxy3.sayHelloworld();
测试结果如下:
【拦截器3】的before方法
【拦截器2】的before方法
【拦截器1】的before方法
sayHello
【拦截器1】的after方法
【拦截器2】的after方法
【拦截器3】的 after方法
before方法按照从最后一个拦截器到第一个拦截器的加载顺序运行,而after方法则按照从第一个拦截器到最后一个拦截器的加载顺序运行。 从代码中可见,责任链模式的优点在于我们可以在传递链上加入新的拦截器,增加拦截逻辑,其缺点是会增加代理和反射,而代理和反射的性能不高。
|