java动态代理:JDK动态代理的内部原理

Posted pgrDog

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java动态代理:JDK动态代理的内部原理相关的知识,希望对你有一定的参考价值。

上一章我们简单的讲解了什么是动态代理和如何使用动态代理。
这章讲解一下jdk的动态代理的内部实现:
首先查看测试代码:
            
  1. //创建一个静态方法,生成代理类,
  2. public static Object newProxyInstance(Object speak){
  3. System.out.println(JDKDynamicProxy.class.getClassLoader().toString());
  4. return Proxy.newProxyInstance(JDKDynamicProxy.class.getClassLoader(),new Class[]{Speak.class,Eat.class}, new JDKDynamicProxy(speak));
  5. }

从代码可以看出是调用了Proxy.newProxyInstance,进入该方法,查看源代码:
            
  1. @CallerSensitive
  2. public static Object newProxyInstance(ClassLoader loader,
  3. Class<?>[] interfaces,
  4. InvocationHandler h)
  5. throws IllegalArgumentException
  6. {
  7. if (h == null) {
  8. throw new NullPointerException();
  9. }
  10. final Class<?>[] intfs = interfaces.clone();//拷贝一份接口类数组,我们的例子是传入{Speak.class,Eat.class}
  11. final SecurityManager sm = System.getSecurityManager();//获取安全管理器组件
  12. if (sm != null) {//判断是否有权限去访问
  13. checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
  14. }
  15. /*
  16. * Look up or generate the designated proxy class.
  17. */
  18. //根据classloader和接口类数组动态创建Proxy.cass
  19. Class<?> cl = getProxyClass0(loader, intfs);
  20. /*
  21. * Invoke its constructor with the designated invocation handler.
  22. */
  23. try {
  24. //Proxy.class存在一个以InvocationHandler.class为类型的参数,获取该构造器
  25. //看起来是我们常用的代理模式
  26. final Constructor<?> cons = cl.getConstructor(constructorParams);
  27. final InvocationHandler ih = h;
  28. if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(cl)) {//判断是Proxy.class是否包含不是public类型的接口
  29. // create proxy instance with doPrivilege as the proxy class may
  30. // implement non-public interfaces that requires a special permission
  31. return AccessController.doPrivileged(new PrivilegedAction<Object>() {
  32. public Object run() {
  33. return newInstance(cons, ih);
  34. }
  35. });
  36. } else {
  37. //返回Proxy.class实例
  38. return newInstance(cons, ih);
  39. }
  40. } catch (NoSuchMethodException e) {
  41. throw new InternalError(e.toString());
  42. }
  43. }
    从代码可以看出,核心方法是:
           Class<?> cl = getProxyClass0(loader, intfs);
    这个方法根据我们传入的接口类和类加载器(若没有自定义加载器,默认是AppClassLoader),此方法是动态生成实现了我们传入的接口的Proxy.class,还有一个Proxy(InvocationHandler h)构造器,传入我们之前实现了InvocationHandler 接口的实现类JDKDynamicProxy.class,之后的newInstance就是反射创建实例并返回。
    先不管那些权限判断的代码,主要看getProxyClass0方法:
     
  1. private static Class<?> getProxyClass0(ClassLoader loader,
  2. Class<?>... interfaces) {
  3. if (interfaces.length > 65535) {//接口数量不能超过65535,刚好是一个int类型的最大值
  4. throw new IllegalArgumentException("interface limit exceeded");
  5. }
  6. // If the proxy class defined by the given loader implementing
  7. // the given interfaces exists, this will simply return the cached copy;
  8. // otherwise, it will create the proxy class via the ProxyClassFactory
  9. return proxyClassCache.get(loader, interfaces);
  10. }
        我们看一下proxyClassCache的定义:
            
  1. /**
  2. * a cache of proxy classes
  3. */
  4. private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
  5. proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
          proxyClassCache是静态变量,从注解可以看出是缓存动态生成的ProxyClass,以便下次再调用的时候可以跳过动态生成java字节码这一步,我们再看一下WeakCache类(题外话:我本地的jdk是1.7版本,在jdk的rt.jar包里是没有java.lang.reflect.WeakCache这个类的,但运行又没有报错,于是看了一下虚拟机的运行环境里的rt.jar,发现是存在这个类的,而且BiFunction伪函数指针是java8才有的):
        
 

        WeakCache主要的内部类有:CacheKey,CacheValue,Factory,Supplier,Value。
        其中CacheValue实现Supplier的接口中get方法由WeakReference的get方法来实现。
        
        查看WeakCache的成员:
            
  1. private final ReferenceQueue<K> refQueue = new ReferenceQueue();//弱引用队列
  2. //(ClassLoader key ,(<CLassloader,Class<?>[]> key ,Factory value) value)
  3. private final ConcurrentMap<Object, ConcurrentMap<Object, Supplier<V>>> map = new ConcurrentHashMap();
  4. private final ConcurrentMap<Supplier<V>, Boolean> reverseMap = new ConcurrentHashMap();
  5. private final BiFunction<K, P, ?> subKeyFactory;//Key的创建工厂
  6. private final BiFunction<K, P, V> valueFactory;//value的创建工厂

        主要的有map和reverseMap,其中map的key是ClassLoader类型,Value是concurrentMap类型,而concurrentMap里的key是由subKeyFactory组合ClassLoader和接口类数组组合而成,value有两种可能,一种是Factory对象,一种是CacheValue,Factory对象是生产我们需要的ProxyClass的,而CacheValue是存储已经生产过的ProxyClass。
        看主要方法:
                
  1. //调用这个方法获取动态生成的class
  2. public V get(K paramK, P paramP)
  3. {
  4. Objects.requireNonNull(paramP);//检测传入的接口数组是否为空
  5. expungeStaleEntries();//删除因为只有弱引用没有强引用指向的被gc回收后遗留下来的WeakReference对象,
  6. Object localObject1 = CacheKey.valueOf(paramK, this.refQueue); //创建一个CacheKey,paramK是ClassLoader对象,CacheKey是继承WeakReference类,
  7. Object localObject2 = (ConcurrentMap)this.map.get(localObject1);//判断map中是否存在相同的key
  8. if (localObject2 == null)//不存在
  9. {
  10. localObject3 = (ConcurrentMap)this.map.putIfAbsent(localObject1, localObject2 = new ConcurrentHashMap());//不存在则存入<ClassLoader:localObject1,ConcurrentHashMap:localObject2>,若存在则map.get(localObject1)得到localObject3
  11. if (localObject3 != null)
  12. localObject2 = localObject3;
  13. }
  14. Object localObject3 = Objects.requireNonNull(this.subKeyFactory.apply(paramK, paramP));//创建二元键<classloader,Class<?>[]>
  15. Object localObject4 = (Supplier)((ConcurrentMap)localObject2).get(localObject3);//从localObject2根据我们给的<classloader,Class<?>[]>获取Value,有可能是Factory对象,也有可能是CacheValue对象,Factory则调用动态创建ProxyClass,创建完ProxyClass后封装成CacheValue,然后用CacheValue替换掉Factory。
  16. Factory localFactory = null;
  17. while (true)
  18. {
  19. if (localObject4 != null)
  20. {
  21.        //核心代码
  22. Object localObject5 = ((Supplier)localObject4).get();//调用的有可能是Factory的get方法,也有可能是CacheValue的get方法
  23. if (localObject5 != null)
  24. return localObject5;
  25. }
  26. if (localFactory == null)//为该键值<classloader,intfaces>创建一个工厂
  27. localFactory = new Factory(paramK, paramP, localObject3, (ConcurrentMap)localObject2);
  28. if (localObject4 == null)//把创建的工厂放入localObject2中
  29. {
  30. localObject4 = (Supplier)((ConcurrentMap)localObject2).putIfAbsent(localObject3, localFactory);
  31. if (localObject4 != null)
  32. continue;
  33. localObject4 = localFactory;
  34. continue;
  35. }
  36. //当localObject4存在,但Facotry的get方法并返回null时,就替换掉replace(K key, V oldValue, V newValue)
  37. if (((ConcurrentMap)localObject2).replace(localObject3, localObject4, localFactory))
  38. {
  39. localObject4 = localFactory;
  40. continue;
  41. }
  42. localObject4 = (Supplier)((ConcurrentMap)localObject2).get(localObject3);
  43. }
  44. }
               CacheValue的get方法是返回已生成的Class文件,故不再关注,重点关注Factory的get方法
  1. public synchronized V get()
  2. {
  3. //factory获取
  4. WeakCache.Supplier localSupplier = (WeakCache.Supplier)this.valuesMap.get(this.subKey);
  5. if (localSupplier != this)
  6. return null;
  7. Object localObject1 = null;
  8. try
  9. {
  10. //调用ProxyClassFactory的apply,返回Class类型为localObject1
  11. localObject1 = Objects.requireNonNull(WeakCache.this.valueFactory.apply(this.key, this.parameter));
  12. }
  13. finally
  14. {
  15. if (localObject1 == null)
  16. this.valuesMap.remove(this.subKey, this);
  17. }
  18. assert (localObject1 != null);
  19. WeakCache.CacheValue localCacheValue = new WeakCache.CacheValue(localObject1);
  20. //因为Factory和CacheValue都继承Supplier,故可以将原本指向Factory对象替换成指向CacheValue
  21. if (this.valuesMap.replace(this.subKey, this, localCacheValue))
  22. //缓存Class
  23. WeakCache.this.reverseMap.put(localCacheValue, Boolean.TRUE);
  24. else
  25. throw new AssertionError("Should not reach here");
  26. return localObject1;
  27. }
其中WeakCache.this.valueFactory.apply(this.key, this.parameter) 是调用之前
  1. private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
  2. proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
Proxy类的newProxyClassFactory类的apply方法:
            
  1. /**
  2. * A factory function that generates, defines and returns the proxy class given
  3. * the ClassLoader and array of interfaces.
  4. */
  5. private static final class ProxyClassFactory
  6. implements BiFunction<ClassLoader, Class<?>[], Class<?>>
  7. {
  8. // prefix for all proxy class names
  9. //定义类名前缀
  10. private static final String proxyClassNamePrefix = "$Proxy";
  11. // next number to use for generation of unique proxy class names
  12. //生成类序列号和$Proxy组合成类名
  13. private static final AtomicLong nextUniqueNumber = new AtomicLong();
  14. @Override
  15. public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
  16. Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
  17. for (Class<?> intf : interfaces) {
  18. /*
  19. * Verify that the class loader resolves the name of this
  20. * interface to the same Class object.
  21. */
  22.                //循环获取接口类数组
  23. Class<?> interfaceClass = null;
  24. try {
  25.                    加载接口类
  26. interfaceClass = Class.forName(intf.getName(), false, loader);
  27. } catch (ClassNotFoundException e) {
  28. }
  29. if (interfaceClass != intf) {
  30. throw new IllegalArgumentException(
  31. intf + " is not visible from class loader");
  32. }
  33. /*
  34. * Verify that the Class object actually represents an
  35. * interface.
  36. */
  37.                //判断是否接口
  38. if (!interfaceClass.isInterface()) {
  39. throw new IllegalArgumentException(
  40. interfaceClass.getName() + " is not an interface");
  41. }
  42. /*
  43. * Verify that this interface is not a duplicate.
  44. */
  45.                //判断是否有重复的接口
  46. if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {
  47. throw new IllegalArgumentException(
  48. "repeated interface: " +以上是关于java动态代理:JDK动态代理的内部原理的主要内容,如果未能解决你的问题,请参考以下文章

    转JDK动态代理原理

    设计模式 - 动态代理原理及模仿JDK Proxy 写一个属于自己的动态代理

    JDK动态代理实现原理

    动态代理—— CGLIB代理原理

    Java JDK 动态代理(AOP)使用及实现原理分析

    jdk动态代理和cglib动态代理底层实现原理超详细解析(jdk动态代理篇)