/** * 经纪人,动态代理 * * @author 石玉森 **/ public class JDKDynamicProxyFactory<T> implements InvocationHandler { /** * 委托类实例:被代理的真实对象实例 */ private T target; public JDKDynamicProxyFactory(T target) { this.target = target; } /** * * @param proxy 生成的代理类实例 * @param method * @param args * @return * @throws Throwable */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("调用被被代理的方法 before"); Object result = method.invoke(target,args); System.out.println("调用被被代理的方法 after"); return result; } /** * 创建代理类实例 * @return */ public T getProxyInstance(){ ClassLoader classLoader = target.getClass().getClassLoader(); Class[] interfaces = target.getClass().getInterfaces(); Object proxy = Proxy.newProxyInstance(classLoader,interfaces,this); return (T) proxy; } }
JDK动态代理是基于java反射来实现。
** * cglib动态代理实现 * * @author 石玉森 **/ public class CglibDynamicProxyFactory<T> implements MethodInterceptor { /** * 被代理类:委托类 */ private T target; /** * @param o 代理的对象(生成的被代理类的子类实例) * @param method 被代理的方法 * @param objects 被代理的方法的参数 * @param methodProxy 代理的对的方法(生成的被代理类的子类实例) * @return * @throws Throwable */ @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { Object result = null; System.out.println("调用被被代理的方法 before"); // result = method.invoke(o,objects);//不对 result = method.invoke(this.target, objects);//可以 // result = methodProxy.invoke(this.target, objects);//可以 // result = methodProxy.invokeSuper(o, objects);//可以 System.out.println("调用被被代理的方法 after"); return result; } public T getProxyInstance(T target) { this.target=target; Enhancer enhancer = new Enhancer(); //设置创建子类的类,即指定为哪个类产生代理类 enhancer.setSuperclass(target.getClass()); /*设置回调函数 setCallback设置被代理类的public非final方法被调用时的处理类 * */ enhancer.setCallback(this); //通过字节码技术动态创建子类实例 return (T) enhancer.create(); } }
实现原理
代理模式 | 优点 | 缺点 |
---|---|---|
静态代理 | 简单 | 代码不能复用 |
JDK动态代理 | 动态代码生成快 | 执行慢,强制实现接口 |
CGLIB动态代理 | 生成代码慢 | 执行快,不需实现接口 |
/*** * 静态代理:实现List * 随机存取:实现RandomAccess * 克隆:实现Cloneable */ public class CopyOnWriteArrayList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable { final transient ReentrantLock lock = new ReentrantLock(); //委托类。初始化时即实例化,不像虚拟代理懒加载 private transient volatile Object[] array; public boolean add(E e) { final ReentrantLock lock = this.lock; lock.lock(); try { Object[] elements = getArray(); int len = elements.length; Object[] newElements = Arrays.copyOf(elements, len + 1); newElements[len] = e; setArray(newElements); return true; } finally { lock.unlock(); } } }
struts2中的拦截器实现
/** * 服务生产者 * 服务生产者接受到消费方的调用,通过反射调起实际接口 */ ObjectInputStream input = new ObjectInputStream(socket.getInputStream()); try { String interfaceName = input.readUTF(); String methodName = input.readUTF(); Class<?>[] parameterTypes = (Class<?>[]) input.readObject(); Object[] arguments = (Object[]) input.readObject(); ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream()); try { if (!interfaceName.equals(interfaceClazz.getName())) { throw new IllegalAccessException("Interface wrong, export:" + interfaceClazz + " refer:" + interfaceName); } Method method = service.getClass().getMethod(methodName, parameterTypes); Object result = method.invoke(service, arguments); output.writeObject(result); } catch (Throwable t) { output.writeObject(t); } finally { output.close(); } } finally { input.close(); } /** * 服务消费方 * 服务消费方在本地通过代理的模式实例化代理类,代理类内部通过socket调用远程生产者 */ return (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(), new Class<?>[]{interfaceClass}, new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Socket socket =null; try { socket = new Socket(host, port); ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream()); try { output.writeUTF(method.getName()); output.writeObject(method.getParameterTypes()); output.writeObject(args); ObjectInputStream input = new ObjectInputStream(socket.getInputStream()); try { Object result = input.readObject(); return result; } finally { input.close(); } } finally { output.close(); } } finally { socket.close(); } } });
本文分享自微信公众号 - Java学习录(Javaxuexilu),作者:石玉森
原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。
原始发表时间:2019-07-02
本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。
我来说两句