由于动态代理一般比较难理解,一般都会设计一个拦截器接口供开发者使用,这样开发者就只用知道拦截器接口的方法,含义和作用即可,无须知道动态代理是怎么实现的。
以下代码用JDK动态代理来实现一个拦截器的逻辑。
一,定义拦截器接口:
package intercept;import java.lang.reflect.Method;public interface Interceptor { public boolean before(Object proxy, Object target, Method method, Object[] args); public void around(Object proxy, Object target, Method method, Object[] args); public void after(Object proxy, Object target, Method method, Object[] args);}
before方法在真实对象调用前,当返回true时,则反射真实对象,当返回false时,则调用around方法。
二,定义拦截器接口实现类:
package intercept;import java.lang.reflect.Method;public class MyInterceptor implements Interceptor { @Override public boolean before(Object proxy, Object target, Method method, Object[] args) { System.err.println("反射方法前逻辑"); return true; // return false;// 不反射被代理对象原有方法 } @Override public void after(Object proxy, Object target, Method method, Object[] args) { System.err.println("反射方法后逻辑。"); } @Override public void around(Object proxy, Object target, Method method, Object[] args) { System.err.println("取代了被代理对象的方法"); }}
三,在JDK动态代理(JDK动态代理介绍)中使用拦截器:
package intercept;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class InterceptorJdkProxy implements InvocationHandler { private Object target; //真实对象 private String interceptorClass = null;//拦截器全限定名 public InterceptorJdkProxy(Object target, String interceptorClass) { this.target = target; this.interceptorClass = interceptorClass; } /** * 绑定委托对象并返回一个【代理占位】 * * @param target 真实对象 * @return 代理对象【占位】 */ public static Object bind(Object target, String interceptorClass) { //取得代理对象 return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InterceptorJdkProxy(target, interceptorClass)); } @Override /** * 通过代理对象调用方法,首先进入这个方法. * * @param proxy --代理对象 * @param method --方法,被调用方法 * @param args -- 方法的参数 */ //反射出类对象 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; }}
五,定义需要被动态代理的类
因为是JDK动态代理,所以先定义接口:
package intercept;public interface HelloWorld { public void sayHelloWorld();}
实现接口:
package intercept;public class HelloWorldImpl implements HelloWorld { @Override public void sayHelloWorld() { // TODO Auto-generated method stub System.out.println("Hello World"); }}
六,编写测试代码:
package intercept;public class TestInterceptor { public static void main(String[] args) { HelloWorldImpl obj = new HelloWorldImpl();//被代理对象 String myInterceptor = "com.lean.ssm.chapter2.intercept.MyInterceptor";// 自己定义的拦截器全限定名 HelloWorld proxy = (HelloWorld) InterceptorJdkProxy.bind(obj, myInterceptor); proxy.sayHelloWorld(); } }
拦截器可以进一步简化动态代理使用方法,使程序变得简单。
七,参考资料
《java EE 互联网框架整合开发》 杨开振 著
联系客服