Java——静态代理、动态代理
https://blog.csdn.net/giserstone/article/details/17199755
代理的作用:业务类只需要关注业务逻辑本身,保证了业务类的重用性
一 静态代理
特点:
程序运行前就已经存在代理类的字节码文件了,代理类和委托类的关系也在程序运行前就确定了
实现:
代理类继承了被代理类的接口;代理类将被代理类以成员变量的方式引入,在构造函数中初始化被代理类;共同接口中,引用成员变量的方法并在该接口中增加新功能以实现代理类的功能。
缺点:
1)代理对象的一个接口只能服务于一种被代理对象,每有一种代理对象,就要多一个代理方法。
2)代理类在程序一开始就要被加载,增加了内存负担
3)如果接口类增加了一个方法,除了被代理对象要增加这个接口,代理对象也要增加这个接口,增加了程序维护的复杂度
4)只能代理已知的对象
二 动态代理
特点:
动态代理的字节码是在程序运行期间由JVM根据反射机制动态生成的,不存在代理类的字节码文件,代理类和委托类的关系是在程序运行时确定的
实现:
1)实现InvocationHandler接口创建自己的调用处理器
2)给Proxy类提供ClassLoader和代理接口类型数组创建动态代理类
3)以调用处理器类型为参数,利用反射机制得到动态代理类的构造函数
4) 以调用处理器对象为参数,利用动态代理类的构造函数创建动态代理类对象
demo:
接口:
package com.test.aoptest.proxyTest; public interface MyTask { void doing(); void writing(); }
委托类:
package com.test.aoptest.proxyTest; public class MyTaskImpl implements MyTask { @Override public void doing() { System.out.println("doing sth ..."); try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } } @Override public void writing() { System.out.println("writing sth ..."); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } }
调度器:
package com.test.aoptest.proxyTest; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class MyTaskInvocationHandler implements InvocationHandler { private Object delegate; public MyTaskInvocationHandler(Object delegate) { this.delegate = delegate; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { long start = System.currentTimeMillis(); Object result = method.invoke(delegate, args); long end = System.currentTimeMillis(); System.out.println("执行任务耗时"+(end - start)+"毫秒"); return result; } }
主入口:
package com.test.aoptest.proxyTest; import java.lang.reflect.Proxy; public class Client { public static void main(String[] args) { MyTaskImpl myTask = new MyTaskImpl(); MyTask proxy = (MyTask) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{MyTask.class}, new MyTaskInvocationHandler(myTask)); proxy.doing(); proxy.writing(); // System.out.println(proxy.hashCode()); // System.out.println(myTask.hashCode()); // System.out.println(myTask.equals(proxy)); // System.out.println(myTask.toString()); // System.out.println(proxy.toString()); } }
System.identityHashCode(Object) 返回对象的内存地址,不管该对象的类是否重写了hashCode()方法。