这篇文章将为大家详细讲解有关如何在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方法,分别给予这些方法如下逻辑定义:
3个方法的参数为:proxy代理对象、target真实对象、method方法、args运行方法参数;
before方法返回boolean值,它在真实对象前调用。当返回为true时,则反射真实对象的方法;当返回为false时,则调用around方法;
在before方法返回为false的情况下,调用around方法
在反射真实对象方法或者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步,返回结果。
开发者只要知道拦截器的作用就可以编写拦截器了,编写完后可以设置拦截器,这样就完成了任务,所以对于开发者而言相对简单了
设计者可能是精通Java的开发人员,他来完成动态代理的逻辑
设计者只会把拦截器接口暴露给开发者使用,让动态代理的逻辑在开发者的视野中“消失”
拦截器可以进一步简化动态代理的使用方法,使程序变得更简单,用如下的测试类测试一下:
public class Mytest { public static void main(String []args){ HelloWorld proxy1 = (HelloWorld) InterceptorJdkProxy.bind(new HelloWorldImpl(),"com.csdn.blog.interceptor.MyInterceptor"); proxy1.sayHelloWorld(); } }
运行这段代码,得到以下结果:
反射方法前逻辑
取代了被代理对象的方法
反射方法后逻辑
关于如何在Java中利用动态代理实现应用拦截器就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。