您现在的位置是:首页 > 文章详情

JDK动态代理源码解析

日期:2018-06-02点击:337
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_34173549/article/details/80557290

分析版本jdk1.8

在分析jdk动态代理之前,先来了解java WeakReference弱引用的使用。运行期创建目标对象的代理非常耗时,使用缓存来存储生成的代理类显得尤为重要。jdk动态代理使用弱引用指向cache中的代理类,以便代理类对象能够被GC回收。


在java中,当一个对象O被创建时,它被放在Heap里,当GC运行的时候,如果发现没有任何引用指向O,O就会被回收以腾出内存空间,或者说,一个对象被回收,必须满足两个条件:1)没有任何引用指向它;2)GC被运行。在现实情况写代码的时候, 我们往往通过把所有指向某个对象的referece置空来保证这个对象在下次GC运行的时候被回收 (可以用java -verbose:gc来观察gc的行为)。

[java]  view plain  copy
  1. Object c = new Car();  
  2. c=null;  
但是, 手动置空对象对于程序员来说, 是一件繁琐且违背自动回收的理念的.  对于简单的情况, 手动置空是不需要程序员来做的, 因为在java中, 对于简单对象, 当调用它的方法执行完毕后, 指向它的引用会被从stack中popup, 所以他就能在下一次GC执行时被回收了.
但是, 也有特殊例外. 当使用cache的时候, 由于cache的对象正是程序运行需要的, 那么只要程序正在运行, cache中的引用就不会被GC给(或者说, cache中的reference拥有了和主程序一样的life cycle). 那么随着cache中的reference越来越多, GC无法回收的object也越来越多, 无法被自动回收. 当这些object需要被回收时, 回收这些object的任务只有交给程序编写者了. 然而这却违背了GC的本质(自动回收可以回收的objects).所以, java中引入了weak reference. 相对于前面举例中的strong reference:

[java]  view plain  copy
  1. Object c = new Car(); //只要c还指向car object, car object就不会被回收  
当一个对象仅仅被weak reference指向, 而没有任何其他strong reference指向的时候, 如果GC运行, 那么这个对象就会被回收. weak reference的语法是:

[java]  view plain  copy
  1. WeakReference<Car> weakCar = new WeakReference(Car)(car);  

当要获得weak reference引用的object时, 首先需要判断它是否已经被回收:

[java]  view plain  copy
  1. weakCar.get();  
 如果此方法为空, 那么说明weakCar指向的对象已经被回收了,下面来看一个例子:
[java]  view plain  copy
  1. package weakreference;  
  2. /** 
  3.  * @author ywchen 
  4.  */  
  5. public class Car {  
  6.     private double price;  
  7.     private String colour;  
  8.       
  9.     public Car(double price, String colour){  
  10.         this.price = price;  
  11.         this.colour = colour;  
  12.     }  
  13.     public double getPrice() {  
  14.         return price;  
  15.     }  
  16.     public void setPrice(double price) {  
  17.         this.price = price;  
  18.     }  
  19.     public String getColour() {  
  20.         return colour;  
  21.     }  
  22.     public void setColour(String colour) {  
  23.         this.colour = colour;  
  24.     }  
  25.       
  26.     public String toString(){  
  27.         return colour +"car costs $"+price;  
  28.     }     
  29. }  
  30. package weakreference;  
  31.   
  32. import java.lang.ref.WeakReference;  
  33.   
  34. /** 
  35.  * @author ywchen 
  36.  */  
  37. public class TestWeakReference {  
  38.     public static void main(String[] args) {  
  39.         Car car = new Car(22000,"silver");  
  40.         WeakReference<Car> weakCar = new WeakReference<Car>(car);  
  41.         int i=0;  
  42.         while(true){  
  43.             if(weakCar.get()!=null){  
  44.                 i++;  
  45.                 System.out.println("Object is alive for "+i+" loops - "+weakCar);  
  46.             }else{  
  47.                 System.out.println("Object has been collected.");  
  48.                 break;  
  49.             }  
  50.         }  
  51.     }  
  52. }  


在上例中, 程序运行一段时间后, 程序打印出"Object has been collected." 说明, weak reference指向的对象的被回收了.


ReferenceQueue
在weak reference指向的对象被回收后, weak reference本身其实也就没有用了. java提供了一个ReferenceQueue来保存这些所指向的对象已经被回收的reference. 用法是在定义WeakReference的时候将一个ReferenceQueue的对象作为参数传入构造函数.


jdk动态代理

面向对象编程(OOP)有一些弊端,为多个不具有继承关系的对象引入同一个公共行为,例如日志、安全监测等,需要在每个对象里引入公共行为,导致程序中产生大量重复代码。不便于维护。所以就有了一个面向对象编程的补充,即面向切面编程(AOP),AOP所关注的是横向,OOP关注的是纵向。AOP的实现,可采用JDK动态代理、CGLIB代理。

JDK动态代理:其代理对象必须是某个接口的实现,它是通过在运行期间创建一个接口的实现来完成目标对象的代理。

CBLIB代理:实现原理类似于JDK动态代理,它在运行期间生成的代理对象是针对目标类扩展的子类。CGLIB是高效的代码生成包,底层依靠ASM(开源的字节码编辑类库)操作字节码实现,性能比JDK强。

jdk动态代理实现示例

1. 新建委托类

[java]  view plain  copy
  1. /**  
  2.  * 目标对象实现的接口,用JDK来生成代理对象一定要实现一个接口  
  3.  * @author yawenchen  
  4.  * @since 2016-11-15  
  5.  *  
  6.  */    
  7. public interface UserService {    
  8.     
  9.     /**  
  10.      * 目标方法   
  11.      */    
  12.     public abstract void add();    
  13.     
  14. }    
[java]  view plain  copy
  1. /**  
  2.  * 目标对象  
  3.  * @author yawenchen  
  4.  * @since 2016-11-15  
  5.  *  
  6.  */    
  7. public class UserServiceImpl implements UserService {    
  8.   
  9.  /* (non-Javadoc)  
  10.      * @see dynamic.proxy.UserService#add()  
  11.      */    
  12.     public void add() {    
  13.         System.out.println("--------------------add---------------");    
  14.     }    
  15. }    
UserService 是一个接口,UserServiceImpl 接口的实现类,也称委托类。动态代理要求代理对象必须是接口的实现类。因此UserServiceImpl 实现了UserService 。


2. 实现InvocationHandlerj接口

[java]  view plain  copy
  1. import java.lang.reflect.InvocationHandler;    
  2. import java.lang.reflect.Method;    
  3. import java.lang.reflect.Proxy;    
  4.     
  5. /**  
  6.  * 实现自己的InvocationHandler  
  7.  * @author ywchen  
  8.  * @since 2016-11-15  
  9.  *  
  10.  */    
  11. public class MyInvocationHandler implements InvocationHandler {    
  12.         
  13.     // 目标对象     
  14.   private Object target;    
  15.         
  16.     /**  
  17.      * 构造方法  
  18.      * @param target 目标对象   
  19.      */    
  20.     public MyInvocationHandler(Object target) {    
  21.         super();    
  22.         this.target = target;    
  23.     }    
  24.     
  25.     
  26.     /**  
  27.  * 执行目标对象的方法  
  28.      */    
  29. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {    
  30.         
  31.         // 在目标对象的方法执行之前简单的打印一下    
  32.         System.out.println("------------------before------------------");    
  33.             
  34.         // 执行目标对象的方法    
  35.         Object result = method.invoke(target, args);    
  36.             
  37.         // 在目标对象的方法执行之后简单的打印一下    
  38.         System.out.println("-------------------after------------------");    
  39.   
  40.         return result;    
  41.     }    
  42.     
  43. /**  
  44.      * 获取目标对象的代理对象  
  45.      * @return 代理对象  
  46.      */    
  47.     public Object getProxy() {    
  48.         return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),     
  49.                 target.getClass().getInterfaces(), this);    
  50.     }    
  51. }    
target属性,表示代理的目标对象。InvocationHandler是负责连接代理对象与目标对象的自定义中间类MyInvocationHandler必须实现的接口,只有一个方法。
public Object invoke(Object proxy, Method method, Object[] args)
参数说明:Proxy表示通过Proxy.newProxyInstance()生成的代理类对象。Method表示目标对象被调用的方法。Args表示目标对象被调用方法的输入参数。

3. 通过Proxy类静态函数生成代理对象

[java]  view plain  copy
  1. public class ProxyTest {  
  2.     public static void main(String[] args) {  
  3.                 //实例化目标对象  
  4.         UserService userService  = new UserSericeImpl();  
  5.         //实例化InvocationHander  
  6.         MyInvocationHandler invocationHandler = new MyInvocationHandler(userService);  
  7.         //根据目标对象生成代理对象  
  8.         UserService proxy = (UserService)invocationHandler.getProxy();  
  9.         //调用代理对象的方法  
  10.         proxy.add();  
  11.     }  
  12. }  

执行结果
------------------before------------------ 
--------------------add--------------- 
-------------------after------------------ 


动态代理原理

[java]  view plain  copy
  1. /** 
  2. * loader :类加载器 
  3. * interfaces:目标对象实现的接口 
  4. * h:InvocationHandler的实现类 
  5. */  
  6.     public static Object newProxyInstance(ClassLoader loader,  
  7.                                           Class<?>[] interfaces,  
  8.                                           InvocationHandler h)  
  9.         throws IllegalArgumentException  
  10.     {  
  11.         Objects.requireNonNull(h);  
  12.   
  13.         final Class<?>[] intfs = interfaces.clone();  
  14.         final SecurityManager sm = System.getSecurityManager();  
  15.         if (sm != null) {  
  16.             checkProxyAccess(Reflection.getCallerClass(), loader, intfs);  
  17.         }  
  18.   
  19.         /* 
  20.          * Look up or generate the designated proxy class.从缓存中查找或生成目标对象的代理类 
  21.          */  
  22.         Class<?> cl = getProxyClass0(loader, intfs);  
  23.   
  24.         /* 
  25.          * Invoke its constructor with the designated invocation handler. 
  26.          */  
  27.         try {  
  28.             if (sm != null) {  
  29.                 checkNewProxyPermission(Reflection.getCallerClass(), cl);  
  30.             }  
  31.           //调用代理对象的构造函数(代理对象的构造函数$Proxy0(InvocationHandler h),通过字节码反编译可以查看生成的代理类)  
  32.             final Constructor<?> cons = cl.getConstructor(constructorParams);  
  33.             final InvocationHandler ih = h;  
  34.             if (!Modifier.isPublic(cl.getModifiers())) {  
  35.                 AccessController.doPrivileged(new PrivilegedAction<Void>() {  
  36.                     public Void run() {  
  37.                         cons.setAccessible(true);  
  38.                         return null;  
  39.                     }  
  40.                 });  
  41.             }  
  42.         //生成代理类的实例,并把MyInvocationHander的实例作为构造函数参数传入  
  43.             return cons.newInstance(new Object[]{h});  
  44.         } catch (IllegalAccessException|InstantiationException e) {  
  45.             throw new InternalError(e.toString(), e);  
  46.         } catch (InvocationTargetException e) {  
  47.             Throwable t = e.getCause();  
  48.             if (t instanceof RuntimeException) {  
  49.                 throw (RuntimeException) t;  
  50.             } else {  
  51.                 throw new InternalError(t.toString(), t);  
  52.             }  
  53.         } catch (NoSuchMethodException e) {  
  54.             throw new InternalError(e.toString(), e);  
  55.         }  
  56. }  

进到getProxyClass0方法
[java]  view plain  copy
  1. private static Class<?> getProxyClass0(ClassLoader loader,  
  2.                                        Class<?>... interfaces) {  
  3.     if (interfaces.length > 65535) {  
  4.         throw new IllegalArgumentException("interface limit exceeded");  
  5.     }  
  6.   
  7.     // If the proxy class defined by the given loader implementing  
  8.     // the given interfaces exists, this will simply return the cached copy;  
  9.     // otherwise, it will create the proxy class via the ProxyClassFactory  
  10.     return proxyClassCache.get(loader, interfaces);  
  11. }  

proxyClassCache为WeakCache的实例化对象,在Proxy类中定义,表示代理类的缓存。定义如下:

[java]  view plain  copy
  1. private static final WeakCache<ClassLoader, Class<?>[], Class<?>>   proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());  

KeyFactory、ProxyClassFactory是WeakCache的内部静态类。实现了BiFunction接口。WeakCache实例化时作为构造函数参数传入,继承关系如下:


主要的代码如下:

[java]  view plain  copy
  1. public interface BiFunction<T, U, R> {  
  2.     R apply(T t, U u);  
  3. }  


[java]  view plain  copy
  1. private static final class ProxyClassFactory  
  2.         implements BiFunction<ClassLoader, Class<?>[], Class<?>>  
  3.     {  
  4.         // prefix for all proxy class names 代理类的前缀  
  5.         private static final String proxyClassNamePrefix = "$Proxy";  
  6.   
  7.         // next number to use for generation of unique proxy class names  
  8.     //生成唯一的代理类名称  
  9.         private static final AtomicLong nextUniqueNumber = new AtomicLong();  
  10.   
  11.         @Override  
  12.         public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {  
  13.   
  14.             Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);  
  15.             for (Class<?> intf : interfaces) {  
  16.                 /* 
  17.                  * Verify that the class loader resolves the name of this 
  18.                  * interface to the same Class object. 
  19.                  */  
  20.         //确保接口的类对象与类加载器加载的类对象相同,且由同一个加载器加载。《深入理解java虚拟机》提到,类加载器虽然只用于实现类的加载动作,但在java程序起的作用远不止于类的加载。对于任何一个类,都需要由加载它的的类加载器和这个类本身一同确立其在java虚拟机中的唯一性,每一个类加载器,都拥有一个独立的类名称空间,通俗点,比较两个类是否相等,只有在这两个类是由同一个类加载器加载的前提下才有意义,否则,即使这两个类来源于同一个class文件,被同一个虚拟机加载,只要加载它们的类加载器不同,那这两个类就必定不相等。interfaceClass = Class.forName(intf.getName(), false, loader);验证类是否相等,实现原理如上所述。  
  21.   
  22.                 Class<?> interfaceClass = null;  
  23.                 try {  
  24.                     interfaceClass = Class.forName(intf.getName(), false, loader);  
  25.                 } catch (ClassNotFoundException e) {  
  26.                 }  
  27.                 if (interfaceClass != intf) {  
  28.                     throw new IllegalArgumentException(  
  29.                         intf + " is not visible from class loader");  
  30.                 }  
  31.                 /* 
  32.                  * Verify that the Class object actually represents an 
  33.                  * interface. 验证类对象表示的是接口 
  34.                  */  
  35.                 if (!interfaceClass.isInterface()) {  
  36.                     throw new IllegalArgumentException(  
  37.                         interfaceClass.getName() + " is not an interface");  
  38.                 }  
  39.                 /* 
  40.                  * Verify that this interface is not a duplicate. 验证接口未重复 
  41.                  */  
  42.                 if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {  
  43.                     throw new IllegalArgumentException(  
  44.                         "repeated interface: " + interfaceClass.getName());  
  45.                 }  
  46.             }  
  47.   
  48.             String proxyPkg = null;     // package to define proxy class in定义待生成的代理类所在包名  
  49.             int accessFlags = Modifier.PUBLIC | Modifier.FINAL;  
  50.   
  51.             /* 
  52.              * Record the package of a non-public proxy interface so that the 
  53.              * proxy class will be defined in the same package.  Verify that 
  54.              * all non-public proxy interfaces are in the same package.非public修饰的代理接口,需要定义在相同的包中,如果非public修饰的接口不在相同包,会因访问权限的限制而无法访问。intf.getModifiers()返回的是一个整数,用不同的位开关表示接口中public/final修饰符的使用情况。 
  55.              */  
  56.             for (Class<?> intf : interfaces) {  
  57.                 int flags = intf.getModifiers();  
  58.                 if (!Modifier.isPublic(flags)) {  
  59.                     accessFlags = Modifier.FINAL;  
  60.                     String name = intf.getName();  
  61.                     int n = name.lastIndexOf('.');  
  62.                     String pkg = ((n == -1) ? "" : name.substring(0, n + 1));  
  63.                     if (proxyPkg == null) {  
  64.                         proxyPkg = pkg;   //代理对象的包名,如com.aop  
  65.                     } else if (!pkg.equals(proxyPkg)) {  
  66.                         throw new IllegalArgumentException(  
  67.                             "non-public interfaces from different packages");  
  68.                     }  
  69.                 }  
  70.             }  
  71.   
  72.             if (proxyPkg == null) {  
  73.                 // if no non-public proxy interfaces, use com.sun.proxy package  
  74.                 proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";  
  75.             }  
  76.   
  77.             /* 
  78.              * Choose a name for the proxy class to generate. 
  79.              */  
  80.             long num = nextUniqueNumber.getAndIncrement();  
  81.             String proxyName = proxyPkg + proxyClassNamePrefix + num;  
  82.   
  83.             /* 
  84.              * Generate the specified proxy class. 
  85.          *生成目标对象的代理类的字节码,并保存到硬盘中。 
  86.              */  
  87.             byte[] proxyClassFile = ProxyGenerator.generateProxyClass(  
  88.                 proxyName, interfaces, accessFlags);  
  89.             try {  
  90.         //返回代理类对象,将字节码加载到内存中  
  91.                 return defineClass0(loader, proxyName,  
  92.                                     proxyClassFile, 0, proxyClassFile.length);  
  93.             } catch (ClassFormatError e) {  
  94.                 /* 
  95.                  * A ClassFormatError here means that (barring bugs in the 
  96.                  * proxy class generation code) there was some other 
  97.                  * invalid aspect of the arguments supplied to the proxy 
  98.                  * class creation (such as virtual machine limitations 
  99.                  * exceeded). 
  100.                  */  
  101.                 throw new IllegalArgumentException(e.toString());  
  102.             }  
  103.         }  
  104.     }  

[java]  view plain  copy
  1. /** 
  2. *映射接口数组到最后键的函数 
  3. * 接口数组映射到最优键对象上(如实例化Key1时,接口作为Key1的构造函数参数,保存到Key1中), 同时,Key1/Key2/KeyX继承了WeakReference弱引用类类,因此接口所在的类对象被弱引用 
  4. */  
  5.    private static final class KeyFactory  
  6.         implements BiFunction<ClassLoader, Class<?>[], Object>  
  7.     {  
  8.         @Override  
  9.         public Object apply(ClassLoader classLoader, Class<?>[] interfaces) {  
  10.             switch (interfaces.length) {  
  11.                 case 1return new Key1(interfaces[0]); // the most frequent  
  12.                 case 2return new Key2(interfaces[0], interfaces[1]);  
  13.                 case 0return key0;  
  14.                 defaultreturn new KeyX(interfaces);  
  15.             }  
  16.         }  
  17.     }  

WeakCache类中定义的map变量如下:

[java]  view plain  copy
  1. private final ConcurrentMap<Object, ConcurrentMap<Object, Supplier<V>>> map = new ConcurrentHashMap<>();  

双层map映射,第一层key为ClassLoader,第二层key为接口的弱引用对象,value为代理类的Class对象。怎么看出是弱引用的呢,value中存放的值是一个类,该类继承了弱引用类WeakReference,我们的代理类在对象实例化时,通过构造函数传入。为对象添加引用,可看WeakReference用法。

第一层是类加载器,第二层才是类对象,为什么不用一层,代理类对象作为键呢,这里就涉及到类加载器的使用。记住一点,类的唯一性是由类加载器和类本身共同决定的。

对Supplier接口,Factory类进行说明,接下来的代码中会用到。

调用proxyClassCache.get(loader, interfaces),进入WeakCache的get方法。代码如下:

[java]  view plain  copy
  1. public V get(K key, P parameter) {  
  2.         Objects.requireNonNull(parameter);  
  3.   
  4.         expungeStaleEntries();  
  5.         //refQueue的类型为ReferenceQueue,存放对象的弱引用,CacheKey继承了WeakReference,因此key(ClassLoader)所在对象被弱引用,对象的应用存放在队列refQueue中。  
  6.         Object cacheKey = CacheKey.valueOf(key, refQueue);  
  7.   
  8.         // lazily install the 2nd level valuesMap for the particular cacheKey  
  9.     //生成第一层key,从缓存中获取valuesMap,如果为空,则新建ConcurrentHashMap实例,把当前加载器和ConcurrentHashMap实例放到缓存中。  
  10.         ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);  
  11.         if (valuesMap == null) {  
  12.             ConcurrentMap<Object, Supplier<V>> oldValuesMap  
  13.                 = map.putIfAbsent(cacheKey,  
  14.                                   valuesMap = new ConcurrentHashMap<>());  
  15.             if (oldValuesMap != null) {  
  16.                 valuesMap = oldValuesMap;  
  17.             }  
  18.         }  
  19.   
  20.         // create subKey and retrieve the possible Supplier<V> stored by that  
  21.         // subKey from valuesMap  
  22.     //subKeyFactory是Proxy类的内部静态类KeyFactory的实例对象  
  23.     //valueFactory是Proxy类的内容静态类ProxyClassFactory的实例对象  
  24.     //subKeyFactory.apply(key, parameter)返回接口的弱引用对象。subKey,即接口的弱引用对象作为第二层映射的键  
  25.         Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));  
  26.         Supplier<V> supplier = valuesMap.get(subKey);  
  27.         Factory factory = null;  
  28.   
  29.         while (true) {  
  30.             if (supplier != null) {  
  31.                 // supplier might be a Factory or a CacheValue<V> instance,supplier不为空,缓存中存在代理类  
  32.                 V value = supplier.get();  
  33.                 if (value != null) {  //value不为空,即代理类存在,将代理类返回。  
  34.                     return value;  
  35.                 }  
  36.             }  
  37.             // else no supplier in cache  
  38.             // or a supplier that returned null (could be a cleared CacheValue  
  39.             // or a Factory that wasn't successful in installing the CacheValue)  
  40.   
  41.             // lazily construct a Factory  
  42.             if (factory == null) {  
  43.                 factory = new Factory(key, parameter, subKey, valuesMap);  
  44.             }  
  45.   
  46.             if (supplier == null) {  
  47.                 supplier = valuesMap.putIfAbsent(subKey, factory);  
  48.                 if (supplier == null) {  
  49.                     // successfully installed Factory  
  50.                     supplier = factory;  
  51.                 }  
  52.                 // else retry with winning supplier  
  53.             } else {  
  54.                 if (valuesMap.replace(subKey, supplier, factory)) {  
  55.                     // successfully replaced  
  56.                     // cleared CacheEntry / unsuccessful Factory  
  57.                     // with our Factory  
  58.                     supplier = factory;  
  59.                 } else {  
  60.                     // retry with current supplier  
  61.                     supplier = valuesMap.get(subKey);  
  62.                 }  
  63.             }  
  64.         }  
  65.     }  

上面执行流程中,主要的两个步骤为:

Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter)); subKey为接口对象的弱引用。 进入Proxy类的内部静态类KeyFactory,查看apply方法(本文前面提到的KeyFactory类)。

V value = supplier.get(); value为缓存中的代理类对象,Supplier是个接口,实现代码是在接口的实现类Factory中, 进入WeakCache类的内部类Factory,查看get方法。如下:

Supplier是接口

[java]  view plain  copy
  1. public interface Supplier<T> {  
  2.   
  3.     /** 
  4.      * Gets a result. 
  5.      * 
  6.      * @return a result 
  7.      */  
  8.     T get();  
  9. }  
  10. }  


Factory是WeakCache的内部类, Factory实现了接口Supplier

[java]  view plain  copy
  1. private final class Factory implements Supplier<V> {  
  2.   
  3.         private final K key;  
  4.         private final P parameter;  
  5.         private final Object subKey;  
  6.         private final ConcurrentMap<Object, Supplier<V>> valuesMap;  
  7.   
  8.         Factory(K key, P parameter, Object subKey,  
  9.                 ConcurrentMap<Object, Supplier<V>> valuesMap) {  
  10.             this.key = key;  
  11.             this.parameter = parameter;  
  12.             this.subKey = subKey;  
  13.             this.valuesMap = valuesMap;  
  14.         }  
  15.   
  16.         @Override  
  17.         public synchronized V get() { // serialize access  
  18.             // re-check  
  19.             Supplier<V> supplier = valuesMap.get(subKey);  
  20.             if (supplier != this) {  
  21.                 // something changed while we were waiting:  
  22.                 // might be that we were replaced by a CacheValue  
  23.                 // or were removed because of failure ->  
  24.                 // return null to signal WeakCache.get() to retry  
  25.                 // the loop  
  26.                 return null;  
  27.             }  
  28.             // else still us (supplier == this)  
  29.   
  30.             // create new value  
  31.             V value = null;  
  32.             try {  
  33.             //valueFactory.apply(key, parameter) 返回代理类对象,即Class对象。  
  34.             //如果value不为空,说明缓存中已经存在代理类,可以直接返回。  
  35.             //通过前面的判断,已经能确定缓存中存在代理类,否则,程序是走不到这里来的。  
  36.                 value = Objects.requireNonNull(valueFactory.apply(key, parameter));  
  37.             } finally {  
  38.                 if (value == null) { // remove us on failure  
  39.                     valuesMap.remove(subKey, this);  
  40.                 }  
  41.             }  
  42.             // the only path to reach here is with non-null value  
  43.             assert value != null;  
  44.   
  45.             // wrap value with CacheValue (WeakReference)  
  46.             CacheValue<V> cacheValue = new CacheValue<>(value);  
  47.   
  48.             // try replacing us with CacheValue (this should always succeed)  
  49.             if (valuesMap.replace(subKey, this, cacheValue)) {  
  50.                 // put also in reverseMap  
  51.                 reverseMap.put(cacheValue, Boolean.TRUE);  
  52.             } else {  
  53.                 throw new AssertionError("Should not reach here");  
  54.             }  
  55.   
  56.             // successfully replaced us with new CacheValue -> return the value  
  57.             // wrapped by it  
  58.             return value;  
  59.         }  
  60. }  
在Facotry类的get方法中,value是由valueFactory.apply(key, parameter)生成,返回代理类Class对象。具体的实现可在本文前面提到的ValueFactory中查看。


JDK动态代理实现原理

Java WeakReference的理解与使用

原文链接:https://yq.aliyun.com/articles/653068
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章