Jdk动态代理&拦截器
1. 环境搭建
1.1. 创建接口
由于使用Jdk动态代理必须使用接口,所以需要先创建一个接口:JDKReflect
public interface JDKReflect { public void print(); public void print2(String str); }
1.2. 创建接口实现类
public class JDKReflectImpl implements JDKReflect { @Override public void print() { System.out.println("这是JDK方式的代理机制..."); } @Override public void print2(String str) { System.out.println("这是JDK方式的代理机制..."+str); } }
2. 创建拦截器
2.1. 创建拦截器接口
package com.itlearn.interceptor; import java.lang.reflect.Method; public interface Interceptor { /** * 在真实对象方法调用之前调用,返回true时,则调用真实对象方法,false调用around方法 * @param proxy :代理对象 * @param target :真实对象 * @param method :当前调度方法 * @param args :方法参数 * @return */ public boolean before(Object proxy, Object target, Method method,Object[] args); public void around(Object proxy, Object target, Method method,Object[] args); //最终都要调用after方法 public void after(Object proxy, Object target, Method method,Object[] args); }
2.2. 创建接口实现类
package com.itlearn.interceptor.impl; import com.itlearn.interceptor.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; } @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("反射方法后逻辑..."); } }
3. 实现动态代理
3.1. 创建动态代理类
package com.itlearn.proxy; import com.itlearn.interceptor.Interceptor; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * 使用拦截器的JDK动态代理类 */ public class InterceptorJdkProxy implements InvocationHandler{ //保存真实对象 private Object target = null; //保存拦截器对象全限定类名,以供反射创建拦截器对象 private 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){ //获取代理对象 Object proxy = Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InterceptorJdkProxy(target, interceptorClass)); return proxy; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //判断是否启用拦截器,如果无拦截器则直接调用方法 if (interceptorClass == null){ return method.invoke(proxy,args); } Object result = null; //通过反射生成拦截器 Interceptor interceptor = (Interceptor) Class.forName(interceptorClass).getDeclaredConstructor().newInstance(); //首先执行拦截器before方法 if (interceptor.before(proxy,target,method,args)){ //前置方法返回true,调用原有对象方法 result = method.invoke(proxy,args); }else { //前置方法返回false,调用around方法 interceptor.around(proxy,target,method,args); } //不管前置方法返回true/false都会执行后置方法 interceptor.after(proxy,target,method,args); return result; } }
3.2. 代理测试
@Test public void test(){ JDKReflect reflect = (JDKReflect) InterceptorJdkProxy.bind(new JDKReflectImpl(),MyInterceptor.class.getName()); reflect.print(); }
3.3. 代码流程解析
- InterceptorJdkProxy.bind(new JDKReflectImpl(),MyInterceptor.class.getName());会执行代理类的bind方法,实现真实对象与代理对象之间的绑定,并返回生成的代理对象。
- 其中:Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InterceptorJdkProxy(target, interceptorClass));中,第三个参数new InterceptorJdkProxy(target, interceptorClass)则代表代理类本身,根据传递进来的真实对象和拦截器全限定类名,会调用代理类的构造器,实现真实对象target和拦截器interceptorClass的赋值。
- 生成代理对象后,使用代理对象调用方法:reflect.print();,则会进入代理类的invoke方法内部。
- 首先判断是否启用了拦截器,即拦截器全限定类名interceptorClass是否为null。由于在bind方法中创建代理对象时,第三个参数的缘故,该interceptorClass已经赋值。所以不是null,代表要启用拦截器。
- 启用拦截器就要生成拦截器的对象,这里使用反射技术:Class.forName(interceptorClass).getDeclaredConstructor().newInstance()。
- 开始调用拦截器方法,首先判断前置方法before是返回true/false,true——>直接调用原有方法,false——>执行around方法。
- 最终执行after方法。
- 返回执行结果result。
3.4. 执行结果
反射方法前逻辑... 取代了被代理对象的方法... 反射方法后逻辑...
可见:拦截器已经生效。