JDK动态代理[2]----JDK动态代理的底层实现

public static Object newProxyInstance(ClassLoader loader,
                                      Class<?>[] interfaces,
                                      InvocationHandler h) throws IllegalArgumentException {
    //验证传入的InvocationHandler不能为空
    Objects.requireNonNull(h);
    //复制代理类实现的所有接口
    final Class<?>[] intfs = interfaces.clone();
    //获取安全管理器
    final SecurityManager sm = System.getSecurityManager();
    //进行一些权限检验
    if (sm != null) {
        checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
    }
    //该方法先从缓存获取代理类, 如果没有再去生成一个代理类
    Class<?> cl = getProxyClass0(loader, intfs);
    try {
        //进行一些权限检验
        if (sm != null) {
            checkNewProxyPermission(Reflection.getCallerClass(), cl);
        }
        //获取参数类型是InvocationHandler.class的代理类构造器
        final Constructor<?> cons = cl.getConstructor(constructorParams);
        final InvocationHandler ih = h;
        //如果代理类是不可访问的, 就使用特权将它的构造器设置为可访问
        if (!Modifier.isPublic(cl.getModifiers())) {
            AccessController.doPrivileged(new PrivilegedAction<Void>() {
                public Void run() {
                    cons.setAccessible(true);
                    return null;
                }
            });
        }
        //传入InvocationHandler实例去构造一个代理类的实例
        //所有代理类都继承自Proxy, 因此这里会调用Proxy的构造器将InvocationHandler引用传入
        return cons.newInstance(new Object[]{h});
    } catch (Exception e) {
        //为了节省篇幅, 笔者统一用Exception捕获了所有异常
        throw new InternalError(e.toString(), e);
    }
}
private static Class<?> getProxyClass0(ClassLoader loader,
                                       Class<?>... interfaces) {
    //目标类实现的接口不能大于65535
    if (interfaces.length > 65535) {
        throw new IllegalArgumentException("interface limit exceeded");
    }
    //获取代理类使用了缓存机制
    return proxyClassCache.get(loader, interfaces);
}
//代理类生成工厂
private static final class ProxyClassFactory
                implements BiFunction<ClassLoader, Class<?>[], Class<?>> {
    //代理类名称前缀
    private static final String proxyClassNamePrefix = "$Proxy";
    //用原子类来生成代理类的序号, 以此来确定唯一的代理类
    private static final AtomicLong nextUniqueNumber = new AtomicLong();
    @Override
    public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
        Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
        for (Class<?> intf : interfaces) {
            //这里遍历interfaces数组进行验证, 主要做三件事情
            //1.intf是否可以由指定的类加载进行加载
            //2.intf是否是一个接口
            //3.intf在数组中是否有重复
        }
        //生成代理类的包名
        String proxyPkg = null;
        //生成代理类的访问标志, 默认是public final的
        int accessFlags = Modifier.PUBLIC | Modifier.FINAL;
        for (Class<?> intf : interfaces) {
            //获取接口的访问标志
            int flags = intf.getModifiers();
            //如果接口的访问标志不是public, 那么生成代理类的包名和接口包名相同
            if (!Modifier.isPublic(flags)) {
                //生成的代理类的访问标志设置为final
                accessFlags = Modifier.FINAL;
                //获取接口全限定名, 例如:java.util.Collection
                String name = intf.getName();
                int n = name.lastIndexOf('.');
                //剪裁后得到包名:java.util
                String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
                //生成的代理类的包名和接口包名是一样的
                if (proxyPkg == null) {
                    proxyPkg = pkg;
                } else if (!pkg.equals(proxyPkg)) {
                    //代理类如果实现不同包的接口, 并且接口都不是public的, 那么就会在这里报错
                    throw new IllegalArgumentException(
                        "non-public interfaces from different packages");
                }
            }
        }
        //如果接口访问标志都是public的话, 那生成的代理类都放到默认的包下:com.sun.proxy
        if (proxyPkg == null) {
            proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
        }
        //生成代理类的序号
        long num = nextUniqueNumber.getAndIncrement();
        //生成代理类的全限定名, 包名+前缀+序号, 例如:com.sun.proxy.$Proxy0
        String proxyName = proxyPkg + proxyClassNamePrefix + num;
        //这里是核心, 用ProxyGenerator来生成字节码, 该类放在sun.misc包下
        byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName,
                                  interfaces, accessFlags);
        try {
            //根据二进制文件生成相应的Class实例
            return defineClass0(loader, proxyName, proxyClassFile,
                              0, proxyClassFile.length);
        } catch (ClassFormatError e) {
            throw new IllegalArgumentException(e.toString());
        }
    }
}
//Reference引用队列
private final ReferenceQueue<K> refQueue = new ReferenceQueue<>();
//缓存的底层实现, key为一级缓存, value为二级缓存。 为了支持null, map的key类型设置为Object
private final ConcurrentMap<Object, ConcurrentMap<Object, Supplier<V>>>
                                                       map = new ConcurrentHashMap<>();
//reverseMap记录了所有代理类生成器是否可用, 这是为了实现缓存的过期机制
private final ConcurrentMap<Supplier<V>, Boolean> reverseMap = new ConcurrentHashMap<>();
//生成二级缓存key的工厂, 这里传入的是KeyFactory
private final BiFunction<K, P, ?> subKeyFactory;
//生成二级缓存value的工厂, 这里传入的是ProxyClassFactory
private final BiFunction<K, P, V> valueFactory;

//构造器, 传入生成二级缓存key的工厂和生成二级缓存value的工厂
public WeakCache(BiFunction<K, P, ?> subKeyFactory, BiFunction<K, P, V> valueFactory) {
    this.subKeyFactory = Objects.requireNonNull(subKeyFactory);
    this.valueFactory = Objects.requireNonNull(valueFactory);
}



public V get(K key, P parameter) {
    //这里要求实现的接口不能为空
    Objects.requireNonNull(parameter);
    //清除过期的缓存
    expungeStaleEntries();
    //将ClassLoader包装成CacheKey, 作为一级缓存的key
    Object cacheKey = CacheKey.valueOf(key, refQueue);
    //获取得到二级缓存
    ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);
    //如果根据ClassLoader没有获取到对应的值
    if (valuesMap == null) {
        //以CAS方式放入, 如果不存在则放入,否则返回原先的值
        ConcurrentMap<Object, Supplier<V>> oldValuesMap = map.putIfAbsent(cacheKey,
                valuesMap = new ConcurrentHashMap<>());
        //如果oldValuesMap有值, 说明放入失败
        if (oldValuesMap != null) {
            valuesMap = oldValuesMap;
        }
    }
    //根据代理类实现的接口数组来生成二级缓存key, 分为key0, key1, key2, keyx
    Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
    //这里通过subKey获取到二级缓存的值
    Supplier<V> supplier = valuesMap.get(subKey);
    Factory factory = null;
    //这个循环提供了轮询机制, 如果条件为假就继续重试直到条件为真为止
    while (true) {
        //如果通过subKey取出来的值不为空
        if (supplier != null) {
            //在这里supplier可能是一个Factory也可能会是一个CacheValue
            //在这里不作判断, 而是在Supplier实现类的get方法里面进行验证
            V value = supplier.get();
            if (value != null) {
                return value;
            }
        }
        if (factory == null) {
            //新建一个Factory实例作为subKey对应的值
            factory = new Factory(key, parameter, subKey, valuesMap);
        }
        if (supplier == null) {
            //到这里表明subKey没有对应的值, 就将factory作为subKey的值放入
            supplier = valuesMap.putIfAbsent(subKey, factory);
            if (supplier == null) {
                //到这里表明成功将factory放入缓存
                supplier = factory;
            }
            //否则, 可能期间有其他线程修改了值, 那么就不再继续给subKey赋值, 而是取出来直接用
        } else {
            //期间可能其他线程修改了值, 那么就将原先的值替换
            if (valuesMap.replace(subKey, supplier, factory)) {
                //成功将factory替换成新的值
                supplier = factory;
            } else {
                //替换失败, 继续使用原先的值
                supplier = valuesMap.get(subKey);
            }
        }
    }
}

public V get(K key, P parameter) {
    //这里要求实现的接口不能为空
    Objects.requireNonNull(parameter);
    //清除过期的缓存
    expungeStaleEntries();
    //将ClassLoader包装成CacheKey, 作为一级缓存的key
    Object cacheKey = CacheKey.valueOf(key, refQueue);
    //获取得到二级缓存
    ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);
    //如果根据ClassLoader没有获取到对应的值
    if (valuesMap == null) {
        //以CAS方式放入, 如果不存在则放入,否则返回原先的值
        ConcurrentMap<Object, Supplier<V>> oldValuesMap = map.putIfAbsent(cacheKey,
                valuesMap = new ConcurrentHashMap<>());
        //如果oldValuesMap有值, 说明放入失败
        if (oldValuesMap != null) {
            valuesMap = oldValuesMap;
        }
    }
    //根据代理类实现的接口数组来生成二级缓存key, 分为key0, key1, key2, keyx
    Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
    //这里通过subKey获取到二级缓存的值
    Supplier<V> supplier = valuesMap.get(subKey);
    Factory factory = null;
    //这个循环提供了轮询机制, 如果条件为假就继续重试直到条件为真为止
    while (true) {
        //如果通过subKey取出来的值不为空
        if (supplier != null) {
            //在这里supplier可能是一个Factory也可能会是一个CacheValue
            //在这里不作判断, 而是在Supplier实现类的get方法里面进行验证
            V value = supplier.get();
            if (value != null) {
                return value;
            }
        }
        if (factory == null) {
            //新建一个Factory实例作为subKey对应的值
            factory = new Factory(key, parameter, subKey, valuesMap);
        }
        if (supplier == null) {
            //到这里表明subKey没有对应的值, 就将factory作为subKey的值放入
            supplier = valuesMap.putIfAbsent(subKey, factory);
            if (supplier == null) {
                //到这里表明成功将factory放入缓存
                supplier = factory;
            }
            //否则, 可能期间有其他线程修改了值, 那么就不再继续给subKey赋值, 而是取出来直接用
        } else {
            //期间可能其他线程修改了值, 那么就将原先的值替换
            if (valuesMap.replace(subKey, supplier, factory)) {
                //成功将factory替换成新的值
                supplier = factory;
            } else {
                //替换失败, 继续使用原先的值
                supplier = valuesMap.get(subKey);
            }
        }
    }
}

private byte[] generateClassFile() {
    //第一步, 将所有的方法组装成ProxyMethod对象
    //首先为代理类生成toString, hashCode, equals等代理方法
    addProxyMethod(hashCodeMethod, Object.class);
    addProxyMethod(equalsMethod, Object.class);
    addProxyMethod(toStringMethod, Object.class);
    //遍历每一个接口的每一个方法, 并且为其生成ProxyMethod对象
    for (int i = 0; i < interfaces.length; i++) {
        Method[] methods = interfaces[i].getMethods();
        for (int j = 0; j < methods.length; j++) {
            addProxyMethod(methods[j], interfaces[i]);
        }
    }
    //对于具有相同签名的代理方法, 检验方法的返回值是否兼容
    for (List<ProxyMethod> sigmethods : proxyMethods.values()) {
        checkReturnTypes(sigmethods);
    }

    //第二步, 组装要生成的class文件的所有的字段信息和方法信息
    try {
        //添加构造器方法
        methods.add(generateConstructor());
        //遍历缓存中的代理方法
        for (List<ProxyMethod> sigmethods : proxyMethods.values()) {
            for (ProxyMethod pm : sigmethods) {
                //添加代理类的静态字段, 例如:private static Method m1;
                fields.add(new FieldInfo(pm.methodFieldName,
                        "Ljava/lang/reflect/Method;", ACC_PRIVATE | ACC_STATIC));
                //添加代理类的代理方法
                methods.add(pm.generateMethod());
            }
        }
        //添加代理类的静态字段初始化方法
        methods.add(generateStaticInitializer());
    } catch (IOException e) {
        throw new InternalError("unexpected I/O Exception");
    }

    //验证方法和字段集合不能大于65535
    if (methods.size() > 65535) {
        throw new IllegalArgumentException("method limit exceeded");
    }
    if (fields.size() > 65535) {
        throw new IllegalArgumentException("field limit exceeded");
    }

    //第三步, 写入最终的class文件
    //验证常量池中存在代理类的全限定名
    cp.getClass(dotToSlash(className));
    //验证常量池中存在代理类父类的全限定名, 父类名为:"java/lang/reflect/Proxy"
    cp.getClass(superclassName);
    //验证常量池存在代理类接口的全限定名
    for (int i = 0; i < interfaces.length; i++) {
        cp.getClass(dotToSlash(interfaces[i].getName()));
    }
    //接下来要开始写入文件了,设置常量池只读
    cp.setReadOnly();

    ByteArrayOutputStream bout = new ByteArrayOutputStream();
    DataOutputStream dout = new DataOutputStream(bout);
    try {
        //1.写入魔数
        dout.writeInt(0xCAFEBABE);
        //2.写入次版本号
        dout.writeShort(CLASSFILE_MINOR_VERSION);
        //3.写入主版本号
        dout.writeShort(CLASSFILE_MAJOR_VERSION);
        //4.写入常量池
        cp.write(dout);
        //5.写入访问修饰符
        dout.writeShort(ACC_PUBLIC | ACC_FINAL | ACC_SUPER);
        //6.写入类索引
        dout.writeShort(cp.getClass(dotToSlash(className)));
        //7.写入父类索引, 生成的代理类都继承自Proxy
        dout.writeShort(cp.getClass(superclassName));
        //8.写入接口计数值
        dout.writeShort(interfaces.length);
        //9.写入接口集合
        for (int i = 0; i < interfaces.length; i++) {
            dout.writeShort(cp.getClass(dotToSlash(interfaces[i].getName())));
        }
        //10.写入字段计数值
        dout.writeShort(fields.size());
        //11.写入字段集合
        for (FieldInfo f : fields) {
            f.write(dout);
        }
        //12.写入方法计数值
        dout.writeShort(methods.size());
        //13.写入方法集合
        for (MethodInfo m : methods) {
            m.write(dout);
        }
        //14.写入属性计数值, 代理类class文件没有属性所以为0
        dout.writeShort(0);
    } catch (IOException e) {
        throw new InternalError("unexpected I/O Exception");
    }
    //转换成二进制数组输出
    return bout.toByteArray();
}

public class Proxy0 extends Proxy implements UserDao {

    //第一步, 生成构造器
    protected Proxy0(InvocationHandler h) {
        super(h);
    }

    //第二步, 生成静态域
    private static Method m1;   //hashCode方法
    private static Method m2;   //equals方法
    private static Method m3;   //toString方法
    private static Method m4;   //...

    //第三步, 生成代理方法
    @Override
    public int hashCode() {
        try {
            return (int) h.invoke(this, m1, null);
        } catch (Throwable e) {
            throw new UndeclaredThrowableException(e);
        }
    }

    @Override
    public boolean equals(Object obj) {
        try {
            Object[] args = new Object[] {obj};
            return (boolean) h.invoke(this, m2, args);
        } catch (Throwable e) {
            throw new UndeclaredThrowableException(e);
        }
    }

    @Override
    public String toString() {
        try {
            return (String) h.invoke(this, m3, null);
        } catch (Throwable e) {
            throw new UndeclaredThrowableException(e);
        }
    }

    @Override
    public void save(User user) {
        try {
            //构造参数数组, 如果有多个参数往后面添加就行了
            Object[] args = new Object[] {user};
            h.invoke(this, m4, args);
        } catch (Throwable e) {
            throw new UndeclaredThrowableException(e);
        }
    }

    //第四步, 生成静态初始化方法
    static {
        try {
            Class c1 = Class.forName(Object.class.getName());
            Class c2 = Class.forName(UserDao.class.getName());
            m1 = c1.getMethod("hashCode", null);
            m2 = c1.getMethod("equals", new Class[]{Object.class});
            m3 = c1.getMethod("toString", null);
            m4 = c2.getMethod("save", new Class[]{User.class});
            //...
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值