前一篇文章 我们分析了Java Proxy动态代理类,只是从表面知道他就是打着他人的旗帜,干着自己的勾当! 但是本质上还没有搞清楚它的非法运营模式,这一章我们就来模拟一下犯罪现场,以及解决前一章遗留的问题。模拟开始先~
一、定义委托高层接口
/** * 模拟Java动态代理机制 */ package com.demo.delegator; /** * 定义委托高层接口 * @author Andy * @since 2012.02.17 15:59 PM * @version 1.0 * */ public final class IDelegator { /** * 接口一 * */ public static interface One{ public void sing(); } /** * 接口二 * */ public static interface Two{ public int write(); } /** * 接口三 * */ public static interface Three{ public String read(); } }
二、定义委托实现类
/** * 模拟java动态代理机制 */ package com.demo.delegator.impl; import com.demo.delegator.IDelegator; /** * 委托实现类 * * @author Andy * @see com.demo.delegator.IDelegator.One * @see com.demo.delegator.IDelegator.Two * @see com.demo.delegator.IDelegator.Three * @since 2012.02.17 15:59 PM * @version 1.0 */ public class DelegatorImpl implements IDelegator.One , IDelegator.Two , IDelegator.Three { @Override public String read() { this.print(); return ""; } @Override public int write() { this.print(); return 0; } @Override public void sing() { this.print(); } private void print(){ String message = "Invoke " + Thread.currentThread().getStackTrace()[2].getClassName() + "." + Thread.currentThread().getStackTrace()[2].getMethodName(); System.out.println(message); } }
三、定义代理类
/** * 模拟Java动态代理机制 */ package com.demo.proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import com.demo.delegator.IDelegator; /** * 模拟JAVA动态代理类 * * * JAVA原生动态代理类由ProxyGenerator动态生成实现代理接口的字节码,并注入classloader中。 * 参见源码: * String proxyName = proxyPkg + "$proxy" + num; * byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces); * proxyClass = defineClass0(loader, proxyName, proxyClassFile, 0, proxyClassFile.length); * * 代理机制: * 代理类和委托代理类都实现了代理接口,当代理类调用代理接口时,首先会触发调用处理程序。 * 再由处理程序分发调用委托代理类的接口。从而实现了代理类对委托代理类的隔离。 * * @author Andy * @see com.demo.delegator.IDelegator.One * @see com.demo.delegator.IDelegator.Two * @see com.demo.delegator.IDelegator.Three * @since 2012.02.17 15:59 PM * @version 1.0 */ public final class DynamicProxy implements IDelegator.One , IDelegator.Two , IDelegator.Three { // 引用调用处理对象 private static InvocationHandler handler; private static Class<?>[] interfaces = null; private static Map<Class<?>, DynamicProxy> cachMap = Collections.synchronizedMap(new HashMap<Class<?> , DynamicProxy>()); private DynamicProxy(Class<?>[] interfaces , InvocationHandler handler){ DynamicProxy.handler = handler; DynamicProxy.interfaces = interfaces; } public static Object newInstance(Class<?> clazz, Class<?>[] interfaces,InvocationHandler handler){ DynamicProxy proxy = cachMap.get(clazz); if(null == proxy){ proxy = new DynamicProxy(interfaces , handler); cachMap.put(clazz, proxy); } return proxy; } @Override public String read() { return String.valueOf(this.invoke()); } @Override public int write() { return Integer.valueOf(this.invoke().toString()); } @Override public void sing() { this.invoke(); } private Object invoke(){ Object obj = null; try { StackTraceElement[] elements = Thread.currentThread().getStackTrace(); String methodName = elements[2].getMethodName(); for (int i = 0; i < interfaces.length; i++) { Class<?> clazz = interfaces[i]; Method[] methods = clazz.getMethods(); for (int j = 0; j < methods.length; j++) { Method method = methods[j]; if(methodName.equals(method.getName())){ Class<?> args[] = method.getParameterTypes(); obj = handler.invoke(this, method, args); break; } } } return obj; } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchMethodException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (Throwable e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } }
四、定义委托调用处理程序
/** * */ package com.demo.proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; /** * 委托接口调用处理程序 * * @author Andy * @see java.lang.reflect.InvocationHandler * @since 2012.02.17 15:59 PM * @version 1.0 */ public class AOPHandler implements InvocationHandler { private Object instance = null; private AOPHandler(Class<?> clazz){ try { this.instance = clazz.newInstance(); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static Object getProxyInstance(Class<?> clazz , Class<?> interfaces[]){ return DynamicProxy.newInstance(clazz , interfaces , new AOPHandler(clazz)); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println(method.getName() + " invoke start."); Object returnValue = method.invoke(this.instance, args); System.out.println(method.getName() + " invoke end."); return returnValue; } }
五、模拟代理测试类
/** * 模拟Java动态代理机制 */ package com.demo; import com.demo.delegator.IDelegator; import com.demo.delegator.impl.DelegatorImpl; import com.demo.proxy.AOPHandler; /** * 代理测试类 * @author Andy * */ public class ProxyTest { /** * @param args */ public static void main(String[] args) { // 创建调用处理程序 IDelegator.One proxy = (IDelegator.One)AOPHandler.getProxyInstance(DelegatorImpl.class , DelegatorImpl.class.getInterfaces()); proxy.sing(); } }
总结:委托类与代理类都实现了委托高层接口,故代理类可以处理委托类的请求。当代理类拦截到接口请求时,首先进行委托调用处理程序(所谓的拦截器),在委托调用处理程序中才真正决定是否分发委托类的请求。代理就这样轻松的实现了委托授权,隔离委托类的直接调用。
分析了代理的机制,上一章ProxyGenerator.generateProxyClass(String s, Class clazz[])也不再是个谜。不难推测它就是Proxy的帮凶(子类),并动态实现委托接口,充当代码生成器的凶手。