Appearance
JDK动态代理WeakCache
看在前面
在讨论Proxy类之前,必须先了解这个类。这个类的作用:从其英文意义上来看,它是弱缓存类,即一个起着缓存作用的类。它用来存储弱引用类型的实例,从该类在Proxy类中的实例化可以看出:
java
private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());WeakCache是缓存类加载器以及该加载器加载的委托类的。其中KeyFactory类用来生产Key的,生成因不同数量的类加载器采取不同的生成策略来对应生成的Key对象。
[KeyFactory]((原链已失效 2026-10,内容已在本篇/本库)4%BB%A3%E7%90%86KeyFactory.md)和[ProxyClassFactory]((原链已失效 2026-10,内容已在本篇/本库)4%BB%A3%E7%90%86ProxyClassFactory.md)了解一下。
WeakCache类作用
WeakCache类缓存实现了代理目标接口的类的信息。它也缓存对这些类的一些操作,以及这些类的类加载器。其中重要的方法是get方法。该方法是来获取WeakCache缓存中委托类的Class类对象的,实现了缓存的机制。其源码以及注释如下:
java
public V get(K key, P parameter) {
Objects.requireNonNull(parameter);
//删除过期的缓存
expungeStaleEntries();
//创建CatchKey对象,Key不为空
Object cacheKey = CacheKey.valueOf(key, refQueue);
// 懒惰地为特定的CaseKeKE安装第二级值映射
//根据CatchMap获取ConcurrentMap对象
ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);
//如果没有则创建一个ConcurrentMap对象
if (valuesMap == null) {
ConcurrentMap<Object, Supplier<V>> oldValuesMap
= map.putIfAbsent(cacheKey,
valuesMap = new ConcurrentHashMap<>());
if (oldValuesMap != null) {
valuesMap = oldValuesMap;
}
}
//利用KeyFactory获取Key对象
Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
//利用Key对象取出Supplier,Supplier是一个接口
Supplier<V> supplier = valuesMap.get(subKey);
Factory factory = null;
while (true) {
//不为空,则直接取出
if (supplier != null) {
// 从supplier接口的实现类获取Class类对象
V value = supplier.get();
if (value != null) {
return value;
}
}
//如果supplier为空,进行缓存,Factory是supplier接口的实现类
if (factory == null) {
factory = new Factory(key, parameter, subKey, valuesMap);
}
if (supplier == null) {
supplier = valuesMap.putIfAbsent(subKey, factory);
if (supplier == null) {
//赋值factory
supplier = factory;
}
} else {
//假如不为空,且factory中value为空,则替换factory
if (valuesMap.replace(subKey, supplier, factory)) {
// successfully replaced
// cleared CacheEntry / unsuccessful Factory
// with our Factory
supplier = factory;
} else {
// retry with current supplier
//继续尝试获取接口实现类的supplier类对象
supplier = valuesMap.get(subKey);
}
}
}
}get方法利用ConcurrentMap类来缓存,里面存贮Key对象以及Factory对象。Factory类用来存贮缓存的信息,其实现了Supplier接口。其get方法里面调用了ProxyClassFactory类的apply方法来返回Class类对象。get方法是一个同步的方法,也表明WeakCache缓存是线程安全的。