JDK动态代理源码解析

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: 版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_34173549/article/details/80557290 分析版本jdk1.8在分析jdk动态代理之前,先来了解java WeakReference弱引用的使用。
版权声明:本文为博主原创文章,未经博主允许不得转载。 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的理解与使用

相关文章
|
27天前
|
缓存 Java 程序员
Map - LinkedHashSet&Map源码解析
Map - LinkedHashSet&Map源码解析
60 0
|
7天前
|
消息中间件 缓存 安全
Future与FutureTask源码解析,接口阻塞问题及解决方案
【11月更文挑战第5天】在Java开发中,多线程编程是提高系统并发性能和资源利用率的重要手段。然而,多线程编程也带来了诸如线程安全、死锁、接口阻塞等一系列复杂问题。本文将深度剖析多线程优化技巧、Future与FutureTask的源码、接口阻塞问题及解决方案,并通过具体业务场景和Java代码示例进行实战演示。
26 3
|
13天前
|
设计模式 Java API
[Java]静态代理与动态代理(基于JDK1.8)
本文介绍了代理模式及其分类,包括静态代理和动态代理。静态代理分为面向接口和面向继承两种形式,分别通过手动创建代理类实现;动态代理则利用反射技术,在运行时动态创建代理对象,分为JDK动态代理和Cglib动态代理。文中通过具体代码示例详细讲解了各种代理模式的实现方式和应用场景。
14 0
[Java]静态代理与动态代理(基于JDK1.8)
|
25天前
|
存储
让星星⭐月亮告诉你,HashMap的put方法源码解析及其中两种会触发扩容的场景(足够详尽,有问题欢迎指正~)
`HashMap`的`put`方法通过调用`putVal`实现,主要涉及两个场景下的扩容操作:1. 初始化时,链表数组的初始容量设为16,阈值设为12;2. 当存储的元素个数超过阈值时,链表数组的容量和阈值均翻倍。`putVal`方法处理键值对的插入,包括链表和红黑树的转换,确保高效的数据存取。
50 5
|
22天前
|
Java 关系型数据库 MySQL
【编程基础知识】Eclipse连接MySQL 8.0时的JDK版本和驱动问题全解析
本文详细解析了在使用Eclipse连接MySQL 8.0时常见的JDK版本不兼容、驱动类错误和时区设置问题,并提供了清晰的解决方案。通过正确配置JDK版本、选择合适的驱动类和设置时区,确保Java应用能够顺利连接MySQL 8.0。
102 1
|
26天前
|
Java Spring
Spring底层架构源码解析(三)
Spring底层架构源码解析(三)
|
26天前
|
XML Java 数据格式
Spring底层架构源码解析(二)
Spring底层架构源码解析(二)
|
25天前
|
Java
【编程进阶知识】静态代理、JDK动态代理及Cglib动态代理各自存在的缺点及代码示例
本文介绍了三种Java代理模式:静态代理、JDK动态代理和Cglib动态代理。静态代理针对特定接口或对象,需手动编码实现;JDK动态代理通过反射机制实现,适用于所有接口;Cglib动态代理则基于字节码技术,无需接口支持,但需引入外部库。每种方法各有优缺点,选择时应根据具体需求考虑。
17 1
|
27天前
|
算法 Java 程序员
Map - TreeSet & TreeMap 源码解析
Map - TreeSet & TreeMap 源码解析
31 0
|
27天前
|
算法 Java 容器
Map - HashSet & HashMap 源码解析
Map - HashSet & HashMap 源码解析
49 0

推荐镜像

更多