由于动态代理一般都比较难理解,程序设计者会设计一个拦截器接口供开发者使用,开发者只要知道拦截器接口的方法、含义和作用即可,无须知道动态代理是怎么实现的。用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(); } }
运行这段代码,得到以下结果:
反射方法前逻辑
取代了被代理对象的方法
反射方法后逻辑
显然,拦截器已经生效。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对移动技术网的支持。如果你想了解更多相关内容请查看下面相关链接
如对本文有疑问, 点击进行留言回复!!
网友评论