Java中的代理
2016-07-22 00:00
1036 查看
关于Java中的代理
1. 代理模式
1.1 定义
代理(Proxy)模式标准定义:为其他对象提供一种代理以控制对这个对象的访问。1.2 解释
代理模式可以理解找一个人做我的代理人,可以帮我代理一些事情,但是实际上他只是一个中间人,最后执行的人还是我1.3 类图
1.4 优缺点
优点 : 1. 看起来很直观 2.编译期就已经初始化了,指定了调用顺序,效率高缺点 : 定义的代理类太多,维护困难
1.5 代码实现
Subject 类public interface Subject { public void dosomething(); }
RealSubject 类
public class RealSubject implements Subject { @Override public void dosomething() { System.out.println("dosomething..."); } }
Proxy 类
public class proxy implements Subject{ private Subject subject; public proxy(Subject subject){ this.subject = subject; } @Override public void dosomething() { System.out.println("你好我是subject的代理...."); subject.dosomething(); System.out.println("你看着是我做的,其实是老板做的..."); } }
client 类
public class client { public static void main(String[] args) { proxy p = new proxy(new RealSubject()); p.dosomething(); } }
2.静态代理
静态代理也就是上面的代理模式中实现的例子。但是静态代理必须要保证被代理对象已经实例化,才可以被代理3.JDK 动态代理
3.1 定义
java动态代理机制以巧妙的方式实现了代理模式的设计理念。3.2 解释
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { }
每一个动态代理的类必须实现InvocationHandler,InvocationHandler类是每次调用代理的方法都会触发,并将 代理类,请求的方法,方法参数传入,可以通过反射去执行方法
3.1 优缺点
优点:1.仅需要一个动态代理类 2.在运行期才会去调用,灵活方便缺点:运行期创建效率相对较低,可读性稍差
3.2 代码实现
Subject 类public interface Subject { public void dosomething(); public String sayHello(String username); }
RealSubject类
public class RealSubject implements Subject { @Override public void dosomething() { System.out.println("dosomething..."); } @Override public String sayHello(String username) { return "hello , " + username ; } }
DynamicProxy类
/** * 1. 必须实现<code>InvocationHandler</code><br/> * 2. 在调用方式都会进入到<code>DynamicProxy</code>类中 */ public class DynamicProxy implements InvocationHandler { private Object proxyObject; public DynamicProxy(Object proxyObject){ this.proxyObject = proxyObject; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { return method.invoke(proxyObject,args); } }
client调用
public class client { public static void main(String[] args) { Subject realSubject = new RealSubject(); Subject subject = (Subject) Proxy.newProxyInstance(realSubject.getClass().getClassLoader(),realSubject.getClass().getInterfaces(),new DynamicProxy(realSubject)); String result = subject.sayHello("shanyepifu"); System.out.println(result); subject.dosomething(); } }
4. 通过动态代理和Socket简单实现RPC
服务端代码(暴露服务):public class RPCExporter { public void export(Object inter, int port) throws ServiceUnBindException, PortllegalIIException, IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { // 判断服务是否注册 if (inter == null) { throw new ServiceUnBindException("服务未绑定"); } // 判断端口号是否合法 if (!(Integer.MIN_VALUE < port && port < Integer.MAX_VALUE)) { throw new PortllegalIIException("端口号不合法"); } // 在指定的端口上绑定Socket服务 ServerSocket serverSocket = new ServerSocket(port); while (true) { // socket开始监听端口 Socket socket = serverSocket.accept(); // 获取对象输入、输出流 ObjectInputStream ois = new ObjectInputStream(socket.getInputStream()); ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream()); // 读取传过来的方法信息 String methodName = ois.readUTF(); Class<?>[] parameterTypes = (Class<?>[]) ois.readObject(); Object[] arguments = (Object[]) ois.readObject(); // 通过反射执行方法 Method method = inter.getClass().getMethod(methodName, parameterTypes); Object result = method.invoke(inter, arguments); // 将结果返回 oos.writeObject(result); oos.flush(); // 关闭流 oos.close(); ois.close(); socket.close(); } } }
客户端代码(消费者):
public class RPCRefer { public <T> T refer(Class<T> targetInter, InetAddress inetAddress, int port) throws Exception { // 代理类实现 T target = (T) Proxy.newProxyInstance(targetInter.getClassLoader(), new Class<?>[]{targetInter}, new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Socket socket = new Socket(inetAddress, port); ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream()); oos.writeUTF(method.getName()); oos.writeObject(method.getParameterTypes()); oos.writeObject(args); ObjectInputStream ois = new ObjectInputStream(socket.getInputStream()); Object result = ois.readObject(); if (result instanceof Throwable) { throw (Throwable) result; } return result; } }); return target; } }
完整代码已经托管到码云 : 点击查看
5. cglib动态代理
5.1 定义
CGLib采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。5.2 cglib 和 jdk 动态代理的优缺点(摘录)
(1)Proxy 毕竟是通过反射实现的,必须在效率上付出代价:有实验数据表明,调用反射比一般的函数开销至少要大 10 倍。而且,从程序实现上可以看出,对 proxy class 的所有方法调用都要通过使用反射的 invoke 方法。因此,对于性能关键的应用,使用 proxy class 是需要精心考虑的,以避免反射成为整个应用的瓶颈。(2)CGLib封装了asm,可以再运行期动态生成新的class。ASM 能够通过改造既有类,直接生成需要的代码。增强的代码是硬编码在新生成的类文件内部的,没有反射带来性能上的付出。同时,ASM 与 Proxy 编程不同,不需要为增强代码而新定义一个接口,生成的代码可以覆盖原来的类,或者是原始类的子类。
(3)CGLib在不同频次的调用性能会发生变化,体现为调用频次越高、性能越好。
(4)不同版本的JDK中JDK Proxy的性能也不尽相同,越高版本的JDK(JDK7及以上),性能提升越明显。
5.3 代码实现
Subject类public interface Subject { public void dosomething(); }
RealSubject类
public class RealSubject implements Subject { @Override public void dosomething() { System.out.println("dosomething..."); } }
CglibProxy 类
public class CglibProxy implements MethodInterceptor { private Object target; private Enhancer enhancer = new Enhancer(); public Object getInstance(Class target){ // 设置从字节码创建的类 enhancer.setSuperclass(target); enhancer.setCallback(this); // 创建字节码类 return enhancer.create(); } @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { return methodProxy.invokeSuper(o , objects); } }
client 类
public class client { public static void main(String[] args) { Subject cp = (Subject) new CglibProxy().getInstance(RealSubject.class); cp.dosomething(); } }
相关文章推荐
- springmvc原理及struts2比较&案例&整合&逆向工程&乱码&时间类型转换
- java.sql.Connection.close() vs null
- java AWT容器测试-Frame
- java AWT容器测试-Panel
- java AWT容器测试-ScrollPane
- Java之递归求和的两张方法
- javaweb回顾第五篇浅谈会话
- Retrofit+RxJava
- Java之this关键字的用法
- java中File类浅解析
- Java正则表达式
- Homework--Java_File
- Java泛型深入理解
- Java 实现二分查找\折半查找(速度快的查询有序列表)
- Java版 数字金额大写转换
- java的注释
- Java模拟计算器
- 彻底搞懂Spring类加载(注解方式)
- linphone-LinphoneManager.java文件分析
- Java时间工具类(把日期时间转换成xx秒前、xx分钟前、xx小时前...)