时间:2020-12-23 12:45:01 | 栏目:JAVA代码 | 点击:次
由于动态代理一般都比较难理解,程序设计者会设计一个拦截器接口供开发者使用,开发者只要知道拦截器接口的方法、含义和作用即可,无须知道动态代理是怎么实现的。用JDK动态代理来实现一个拦截器的逻辑,为此先定义拦截器接口Interceptor,如下所示:
/**
* @Auther: haozz
* @Date: 2018/5/27 22:15
* @Description:拦截器接口
**/
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方法,分别给予这些方法如下逻辑定义:
实现这个Interceptor的实现类――MyInterceptor,如下:
/**
* @Auther: haozz
* @Date: 2018/5/27 22:48
* @Description:MyInterceptor
**/
public class MyInterceptor implements Interceptor{
@Override
public boolean before(Object proxy, Object target, Method method, Object[] args) {
System.out.println("反射方法前逻辑");
return false;//不反射被代理对象原有方法
}
@Override
public void around(Object proxy, Object target, Method method, Object[] args) {
System.out.println("取代了被代理对象的方法");
}
@Override
public void after(Object proxy, Object target, Method method, Object[] args) {
System.out.println("反射方法后逻辑");
}
}
它实现了所有Interceptor接口的方法,使用JDK动态代理,就可以去实现这些方法在适当时的调用逻辑了。以上一篇(Java设计模式之动态代理)中的接口和实现类为例,在JDK动态代理中使用拦截器,如下所示:
/**
* @Auther: haozz
* @Date: 2018/5/27 22:30
* @Description:
**/
public class InterceptorJdkProxy implements InvocationHandler {
private Object target;//真实对象
private String interceptorClass = null;//拦截器全限定名
public InterceptorJdkProxy(Object target,String interceptorClass){
this.target = target;
this.interceptorClass = interceptorClass;
}
public static Object bind(Object target,String interceptorClass){
//取得代理对象
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InterceptorJdkProxy(target,interceptorClass));
}
@Override
/**
* Description:通过代理对象调用方法,首先进入这个方法
* @auther: haozz
* @param: proxy 代理对象
* @param: method 被调用方法
* @param: args 方法的参数
* @return: java.lang.Object
* @date: 2018/5/27 23:00
**/
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(target,args);
}else{//返回false执行around方法
interceptor.around(proxy,target,method,args);
}
//调用后置方法
interceptor.after(proxy,target,method,args);
return result;
}
}
这里有两个属性,一个是target,它是真实对象;另一个是字符串interceptorClass,它是一个拦截器的全限定名。解释以下这段代码的执行步骤:
第1步,在bind方法中用JDK动态代理绑定了一个对象,然后返回代理对象;
第2步,如果没有设置拦截器,则直接反射真实对象的方法,然后结束,否则进行第3步;
第3步,通过反射生成拦截器,并准备使用它;
第4步,调用拦截器的before方法,如果返回为true,反射原来的方法;否则运行拦截器的around方法;
第5步,调用拦截器的after方法;
第6步,返回结果。
拦截器可以进一步简化动态代理的使用方法,使程序变得更简单,用如下的测试类测试一下:
public class Mytest {
public static void main(String []args){
HelloWorld proxy1 = (HelloWorld) InterceptorJdkProxy.bind(new HelloWorldImpl(),"com.csdn.blog.interceptor.MyInterceptor");
proxy1.sayHelloWorld();
}
}
运行这段代码,得到以下结果:
反射方法前逻辑
取代了被代理对象的方法
反射方法后逻辑
显然,拦截器已经生效。
总结