参考链接:http://www.jianshu.com/p/3ad3fb560ca1
首先看调用方式:
Subject realSubject = new RealSubject();
InvocationHandler handler = new DynamicProxyHandler(realSubject);
Subject subject = (Subject)Proxy.newProxyInstance(handler.getClass().getClassLoader(), realSubject
.getClass().getInterfaces(), handler);
通过Proxy的
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h);
函数中调用getProxyClass函数,动态生成一个RealSubject类相关的.Class类,newProxyInstance函数中将handler作为回调传递进去,里面调用Proxy类中的static的invoke回调出来也就是到RealSubject的invoke方法中,做一些额外的事情。
// 代理对象是可以序列化
public class Proxy implements Serializable {
一、定义的变量:
1、private static final long serialVersionUID = -2222568056686623797L;
serialVersionUID的作用:
通过判断实体类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体类的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常。
生成实体类的serialVersionUID方法:1、写上默认的1L,比如:private static final long serialVersionUID = 1L; 2、用idea自动生成。
// maps class loaders to created classes by interface names
/** 将代理类 加载器放在Proxy的maps结构中缓存起来 */
2、private static final Map<ClassLoader, Map<String, WeakReference<Class<?>>>> loaderCache = new WeakHashMap<ClassLoader, Map<String, WeakReference<Class<?>>>>();
/** 所有代理类的集合,用于isProxyClass方法的实现 */
3、private static final Map<Class<?>, String> proxyCache = new WeakHashMap<Class<?>, String>();
4、private static int NextClassNameIndex = 0;///** 下一个用于生成唯一代理类名字的数字 */
/**
* The invocation handler on which the method calls are dispatched.
* 代理实例的invocationHandler对象
*/
5、protected InvocationHandler h;
二:定义的方法:
作用类实现了InvocationHandler接口的代理类,其中主要方法有:
private Proxy() {} ("unused") //禁止实例化
protected Proxy(InvocationHandler h):构造方法,用于给内部的h赋值。
static Class getProxyClass(ClassLoader loader, Class[] interfaces):获得一个动态代理类的Class对象。,其中loader是类装载器,interfaces是真实类所拥有的全部接口的数组。 从缓存中取,如果没有,则调用本地方法generateProxy(name, interfaces, loader, methodsArray, exceptionsArray);注意其中的几个参数。
static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h):返回代理类的一个实例,返回后的代理类可以当作被代理类使用。
InvocationHandler.invoke的第一个参数proxy值,是newProxyInstance返回的动态代理类的实例,不是被代理的实例(下方的demo输出的className证明了这一点)。
动态代理类Proxy是结合java底层实现的,通过纯粹的java代码实现比较困难。
需要java动态生成类的支持。
根据class在Map 中查找是否是代理类
public static boolean isProxyClass(Class<?> cl) {}
返回指定代理实例的调用处理程序。
public static InvocationHandler getInvocationHandler(Object proxy) throws IllegalArgumentException {
两个 native方法
native private static Class generateProxy(String name, Class[] interfaces,ClassLoader loader);
在生成代理类时,VM克隆该方法的描述符。没有实现。
native private static void constructorPrototype(InvocationHandler h);
public static void main(String[] args) {
Subject realSubject = new RealSubject();
InvocationHandler handler = new DynamicProxyHandler(realSubject);
Subject subject = (Subject)Proxy.newProxyInstance(handler.getClass().getClassLoader(), realSubject
.getClass().getInterfaces(), handler);
System.out.println(subject.getClass().getName());
subject.rent();
subject.hello("world");
}
subject.getClass().getName()打印的值是:$Proxy0
网友评论