本篇的假設(shè)讀者了解代理模式辽慕,以及會使用Java JDK動(dòng)態(tài)代理卒茬。如果不熟悉,可以先查看另一篇文章:動(dòng)態(tài)代理-Java - 簡書 (jianshu.com)锥惋。
本文將從三個(gè)方面來解析JDK動(dòng)態(tài)代理實(shí)現(xiàn)屋群,分別如下:
- JDK動(dòng)態(tài)代理的使用
- JDK動(dòng)態(tài)生成的代理類結(jié)構(gòu)分析
- JDK動(dòng)態(tài)代理類的生成方式
首先簡要復(fù)習(xí)一下Java JDK動(dòng)態(tài)代理的使用方法,示例:使用JDK動(dòng)態(tài)代理實(shí)現(xiàn)日志打印您宪。
JDK動(dòng)態(tài)代理的使用
首先創(chuàng)建一個(gè)UserDao接口奈懒,UserDao定義了setUserInfo與getUserInfo兩個(gè)方法。
public interface UserDao {
public void setUserInfo(String userInfo);
public String getUserInfo();
}
接著創(chuàng)建UserDao的實(shí)現(xiàn)類UserDaoImpl:
public class UserDaoImpl implements UserDao{
private String userInfo;
@Override
public void setUserInfo(String userInfo) {
this.userInfo = userInfo;
System.out.println("設(shè)置信息:" + userInfo);
}
@Override
public String getUserInfo() {
System.out.println("獲取信息:" + userInfo);
return userInfo;
}
}
然后蚕涤,創(chuàng)建代理邏輯實(shí)現(xiàn)類LogJdkHandler筐赔,該類實(shí)現(xiàn)了java.lang.reflect.InvocationHandler的接口,并且持有被代理的對象的引用:
public class LogJdkHandler implements InvocationHandler{
private Object target;
public LogJdkHandler(Object userDao) {
this.target = userDao;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// proxy是動(dòng)態(tài)生成的代理類的對象
// method是被觸發(fā)的方法
// args是方法入?yún)⒘斜? before();
Object result = method.invoke(target, args);
after();
return result;
}
private void before(){
System.out.println("log before" + (new Date().toString()));
}
private void after(){
System.out.println("log after" + (new Date().toString()));
}
}
最后是為對象創(chuàng)建代理對象:
// 1. 創(chuàng)建代理對象
UserDao userDao = new UserDaoImpl();
// 2. 創(chuàng)建代理的處理類
LogJdkHandler handler = new LogJdkHandler(userDao);
// 3. 使用Proxy.newProxyInstance生成代理對象
UserDao proxy = (UserDao)Proxy.newProxyInstance(
userDao.getClass().getClassLoader(),
userDao.getClass().getInterfaces(),
handler);
proxy.setUserInfo("我是jdk proxy");
System.out.println(proxy.getUserInfo());
創(chuàng)建代理對象調(diào)用的是Proxy.newProxyInstance靜態(tài)方法揖铜,該靜態(tài)方法定義如下:
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
- ClassLoader loader:代理對象的類加載器
- Class<?>[] interfaces:代理類實(shí)現(xiàn)的接口列表
- InvocationHandler:我們自己創(chuàng)建的InvocationHandler對象
傳入上述三個(gè)參數(shù)就可以對象創(chuàng)建代理對象了茴丰。
帶查看源碼前先看一下JDK動(dòng)態(tài)生成的代理類的結(jié)構(gòu)(需在在創(chuàng)建代理對象前運(yùn)行下列代碼):
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");
生成的代理對象字節(jié)碼會被保存在com\sun\proxy
目錄下,反編譯字節(jié)碼可以查看到源碼:
package com.sun.proxy;
import com.maomao.patterndesign.p1_proxy.UserDao;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
public final class $Proxy0 extends Proxy implements UserDao {
private static Method m1;
private static Method m2;
private static Method m3;
private static Method m4;
private static Method m0;
public $Proxy0(InvocationHandler paramInvocationHandler) {
super(paramInvocationHandler);
}
public final boolean equals(Object paramObject) {
try {
return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();
} catch (Error|RuntimeException error) {
throw null;
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
public final String toString() {
try {
return (String)this.h.invoke(this, m2, null);
} catch (Error|RuntimeException error) {
throw null;
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
public final String getUserInfo() {
try {
return (String)this.h.invoke(this, m3, null);
} catch (Error|RuntimeException error) {
throw null;
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
public final void setUserInfo(String paramString) {
try {
this.h.invoke(this, m4, new Object[] { paramString });
return;
} catch (Error|RuntimeException error) {
throw null;
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
public final int hashCode() {
try {
return ((Integer)this.h.invoke(this, m0, null)).intValue();
} catch (Error|RuntimeException error) {
throw null;
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
m3 = Class.forName("com.maomao.patterndesign.p1_proxy.UserDao").getMethod("getUserInfo", new Class[0]);
m4 = Class.forName("com.maomao.patterndesign.p1_proxy.UserDao").getMethod("setUserInfo", new Class[] { Class.forName("java.lang.String") });
m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
return;
} catch (NoSuchMethodException noSuchMethodException) {
throw new NoSuchMethodError(noSuchMethodException.getMessage());
} catch (ClassNotFoundException classNotFoundException) {
throw new NoClassDefFoundError(classNotFoundException.getMessage());
}
}
}
可以看到新創(chuàng)建的代理類$Proxy0繼承了Proxy類并實(shí)現(xiàn)了被代理對象的接口方法天吓。新的代理類有一個(gè)構(gòu)造函數(shù)贿肩,該構(gòu)造函數(shù)入?yún)⑹荌nvocationHandler即我們傳入的LogJdkHandler對象。
public $Proxy0(InvocationHandler paramInvocationHandler) {
super(paramInvocationHandler);
}
構(gòu)造函數(shù)里面通過super(paramInvocationHandler)調(diào)用了父類Proxy的構(gòu)造函數(shù)龄寞,將入?yún)nvocationHandler保存在成員變量里面:
protected InvocationHandler h;
protected Proxy(InvocationHandler h) {
Objects.requireNonNull(h);
this.h = h;
}
還可以看到$Proxy0實(shí)現(xiàn)了getUserInfo和setUserInfo汰规,在實(shí)現(xiàn)類中調(diào)用了如下方法,即調(diào)用了我們自己在LogJdkHandler類實(shí)現(xiàn)的invoke方法物邑。
(String)this.h.invoke(this, m2, null);
第一個(gè)入?yún)⑹谴韺ο蟊旧恚诙€(gè)入?yún)⑹潜挥|發(fā)的方法對象色解,第三個(gè)入?yún)⑹潜挥|發(fā)方法的對象述吸。
到目前為止蝌矛,JDK動(dòng)態(tài)代理生成的代理類結(jié)構(gòu)已經(jīng)很明晰了入撒,那么代理類是被如何動(dòng)態(tài)創(chuàng)建并且加載入內(nèi)存的呢衅金?下一小節(jié)將進(jìn)行一步一步的分析氮唯。
JDK動(dòng)態(tài)代理類的生成方式
(1)Proxy.newProxyInstance
首先我們是通過調(diào)用Proxy.newProxyInstance來創(chuàng)建代理對象豆励,該方法中有關(guān)鍵的三行邏輯:
Class<?> cl = getProxyClass0(loader, intfs);
final Constructor<?> cons = cl.getConstructor(constructorParams);
return cons.newInstance(new Object[]{h});
- 第一行:獲取代理類的Class對象良蒸,首先嘗試從緩存中獲取嫩痰,緩存中沒有則會進(jìn)行創(chuàng)建串纺。
- 第二行:從代理類的Class對象獲取到構(gòu)造函數(shù)纺棺,該構(gòu)造函數(shù)的入?yún)㈩愋蜑閏onstructorParams,在代理類中定義如下帆卓,可以看到獲取的正是InvocationHandler類對象糊啡。
private static final Class<?>[] constructorParams = { InvocationHandler.class };
- 通過反射調(diào)用構(gòu)造函數(shù)來生成代理對象,構(gòu)造函數(shù)入?yún)即為我們傳入的LogJdkHandler對象腺毫。
其中我們要深入了解的是cl.getProxyClass0方法潮酒,查看代理類是如何被生成并加載進(jìn)內(nèi)存的。
(2)cl.getProxyClass0
點(diǎn)擊進(jìn)去getProxyClass0方法可看到如下代碼:
private static Class<?> getProxyClass0(ClassLoader loader,
Class<?>... interfaces) {
if (interfaces.length > 65535) {
throw new IllegalArgumentException("interface limit exceeded");
}
// If the proxy class defined by the given loader implementing
// the given interfaces exists, this will simply return the cached copy;
// otherwise, it will create the proxy class via the ProxyClassFactory
return proxyClassCache.get(loader, interfaces);
}
該方法的入?yún)⑹俏覀冋{(diào)用Proxy.newProxyInstance傳進(jìn)來的被代理對象的類加載器ClassLoader loader與接口列表Class<?>... interfaces勃教。return那行代碼上面的那串英文的意思是如果實(shí)現(xiàn)接口列表的加載器代理類存在的話污抬,方法proxyClassCache.get會直接返回代理類印机,否則該方法會通過ProxyClassFactory工廠類去創(chuàng)建代理類射赛,即調(diào)用proxyClassCache.get方法獲取楣责,那么proxyClassCache是什么呢腐魂?該參數(shù)定義在了Proxy類中蛔屹,如下
private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
proxyClassCache是WeakCache類的對象,我們需要了解的是創(chuàng)建該對象用到了兩個(gè)類的對象以及WeakCache類育叁,分別如下:
① KeyFactory
顧名思義豪嗽,生成key的工廠。生成的key是用來干什么的计贰,key又是怎樣生成的躁倒?這里的解答是褐桌,key是用來作為代理類的唯一標(biāo)志撩嚼,用于獲取類的。至于如何生成的可以查看KeyFactory的定義:
private static final class KeyFactory
implements BiFunction<ClassLoader, Class<?>[], Object>
{
@Override
public Object apply(ClassLoader classLoader, Class<?>[] interfaces) {
switch (interfaces.length) {
case 1: return new Key1(interfaces[0]); // the most frequent
case 2: return new Key2(interfaces[0], interfaces[1]);
case 0: return key0;
default: return new KeyX(interfaces);
}
}
}
點(diǎn)擊進(jìn)入KeyFactory可以看一下它是Proxy類的內(nèi)部類逻族,很一目了然,該類中主要有一個(gè)apply方法要拂,入?yún)⑹鞘煜さ念惣虞d器與接口列表搏嗡。apply方法會根據(jù)類加載器以及接口數(shù)量來生成唯一key采盒,具體如何生成這里不細(xì)致展開了。
② ProxyClassFactory
該類也是Proxy類的內(nèi)部類嫡纠,根據(jù)名稱可以得知除盏,該類是創(chuàng)建代理類的工廠赏迟。
private static final class ProxyClassFactory
implements BiFunction<ClassLoader, Class<?>[], Class<?>>
{
// prefix for all proxy class names
private static final String proxyClassNamePrefix = "$Proxy";
// next number to use for generation of unique proxy class names
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) {
/*
* Verify that the class loader resolves the name of this
* interface to the same Class object.
*/
Class<?> interfaceClass = null;
try {
interfaceClass = Class.forName(intf.getName(), false, loader);
} catch (ClassNotFoundException e) {
}
if (interfaceClass != intf) {
throw new IllegalArgumentException(
intf + " is not visible from class loader");
}
/*
* Verify that the Class object actually represents an
* interface.
*/
if (!interfaceClass.isInterface()) {
throw new IllegalArgumentException(
interfaceClass.getName() + " is not an interface");
}
/*
* Verify that this interface is not a duplicate.
*/
if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {
throw new IllegalArgumentException(
"repeated interface: " + interfaceClass.getName());
}
}
String proxyPkg = null; // package to define proxy class in
int accessFlags = Modifier.PUBLIC | Modifier.FINAL;
/*
* Record the package of a non-public proxy interface so that the
* proxy class will be defined in the same package. Verify that
* all non-public proxy interfaces are in the same package.
*/
for (Class<?> intf : interfaces) {
int flags = intf.getModifiers();
if (!Modifier.isPublic(flags)) {
accessFlags = Modifier.FINAL;
String name = intf.getName();
int n = name.lastIndexOf('.');
String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
if (proxyPkg == null) {
proxyPkg = pkg;
} else if (!pkg.equals(proxyPkg)) {
throw new IllegalArgumentException(
"non-public interfaces from different packages");
}
}
}
if (proxyPkg == null) {
// if no non-public proxy interfaces, use com.sun.proxy package
proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
}
/*
* Choose a name for the proxy class to generate.
*/
long num = nextUniqueNumber.getAndIncrement();
String proxyName = proxyPkg + proxyClassNamePrefix + num;
/*
* Generate the specified proxy class.
*/
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces, accessFlags);
try {
return defineClass0(loader, proxyName,
proxyClassFile, 0, proxyClassFile.length);
} catch (ClassFormatError e) {
/*
* A ClassFormatError here means that (barring bugs in the
* proxy class generation code) there was some other
* invalid aspect of the arguments supplied to the proxy
* class creation (such as virtual machine limitations
* exceeded).
*/
throw new IllegalArgumentException(e.toString());
}
}
}
首先是代理類的兩個(gè)字段,表示代理類的名稱是:類名前綴+編號泻仙。
prefix for all proxy class names
private static final String proxyClassNamePrefix = "$Proxy";
// next number to use for generation of unique proxy class names
private static final AtomicLong nextUniqueNumber = new AtomicLong();
該工廠類的一個(gè)主要方法也是apply方法糕再,入?yún)⒁彩穷惣虞d器與接口列表,用于調(diào)用生成代理類
public Class<?> apply(ClassLoader loader, Class<?>[] interfaces)
其中重要的一行代碼如下
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces, accessFlags);
調(diào)用ProxyGenerator.generateProxyClass方法來生成代理類玉转,該方法實(shí)現(xiàn)如下:
public static byte[] generateProxyClass(final String var0, Class<?>[] var1, int var2) {
ProxyGenerator var3 = new ProxyGenerator(var0, var1, var2);
final byte[] var4 = var3.generateClassFile();
if (saveGeneratedFiles) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
try {
int var1 = var0.lastIndexOf(46);
Path var2;
if (var1 > 0) {
Path var3 = Paths.get(var0.substring(0, var1).replace('.', File.separatorChar));
Files.createDirectories(var3);
var2 = var3.resolve(var0.substring(var1 + 1, var0.length()) + ".class");
} else {
var2 = Paths.get(var0 + ".class");
}
Files.write(var2, var4, new OpenOption[0]);
return null;
} catch (IOException var4x) {
throw new InternalError("I/O exception saving generated file: " + var4x);
}
}
});
}
return var4;
}
該方法的入?yún)?code>var1突想、var2
、var3
分別是類名究抓、接口列表猾担,以及接口實(shí)現(xiàn)方法修飾符標(biāo)志(PUBLIC或者FINAL)。該類首先調(diào)用new ProxyGenerator(var0, var1, var2);
來生成代理生成器var3
然后調(diào)用var3.generateClassFile()
來生成類的byte[]數(shù)組。在返回代理類byte[]數(shù)組之前會判斷是否將代理類保存到磁盤上,即前文我們用于設(shè)置保存代理類文件的一串代碼:
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");
下面來簡要看一下generateClassFile方法
private byte[] generateClassFile() {
this.addProxyMethod(hashCodeMethod, Object.class);
this.addProxyMethod(equalsMethod, Object.class);
this.addProxyMethod(toStringMethod, Object.class);
Class[] var1 = this.interfaces;
int var2 = var1.length;
int var3;
Class var4;
for(var3 = 0; var3 < var2; ++var3) {
var4 = var1[var3];
Method[] var5 = var4.getMethods();
int var6 = var5.length;
for(int var7 = 0; var7 < var6; ++var7) {
Method var8 = var5[var7];
this.addProxyMethod(var8, var4);
}
}
.....
該方法執(zhí)行具體的生成代理類的字節(jié)碼箱歧,可以看到,該方法首先會將Object的hashCode、equals、toString方法加入要代理的方法,然后遍歷接口列表將接口定義的方法加入到要代理的方法中。具體的實(shí)現(xiàn)這里不細(xì)致展開了肌稻,感興趣的可以點(diǎn)擊查看完整的ProxyGenerator類的實(shí)現(xiàn)邏輯。
③ WeakCache類
到這里想必有些暈了,讓我們回到Proxy類的存放代理類的緩存字段proxyClassCache
private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
WeakCache是一個(gè)弱緩存類绑蔫,其類描述如下
Cache mapping pairs of (key, sub-key) -> value. Keys and values are weakly but sub-keys are strongly referenced. Keys are passed directly to get method which also takes a parameter. Sub-keys are calculated from keys and parameters using the subKeyFactory function passed to the constructor. Values are calculated from keys and parameters using the valueFactory function passed to the constructor. Keys can be null and are compared by identity while sub-keys returned by subKeyFactory or values returned by valueFactory can not be null. Sub-keys are compared using their equals method. Entries are expunged from cache lazily on each invocation to get, containsValue or size methods when the WeakReferences to keys are cleared. Cleared WeakReferences to individual values don't cause expunging, but such entries are logically treated as non-existent and trigger re-evaluation of valueFactory on request for their key/subKey.
大致意思是WeakCache可用作Map,可以使用get(key, subKey)的方法來獲取值。在代理類里key是使用我們傳入的類加載器ClassLoader loader
叼风,subKey是接口列表Class<?>... interfaces
作為subKey,值則是我們想要獲取的動(dòng)態(tài)生成的代理類堡妒。從描述中還可以讀到key與value是弱引用,subKey是強(qiáng)引用,弱引用含義如下:
弱引用(Weak Reference):弱引用的對象擁有更短暫的生命周期故河。在垃圾回收器線程掃描它所管轄的內(nèi)存區(qū)域的過程中,一旦發(fā)現(xiàn)了只具有弱引用的對象,不管當(dāng)前內(nèi)存空間足夠與否,都會回收它的內(nèi)存猬仁。
WeakCache類描述中還說到subKey是調(diào)用subKeyFactory計(jì)算得到的帝璧,即是上文中提到的Proxy類的內(nèi)部類KeyFactory的烁,該類有一個(gè)apply方法襟雷,接受classLoader與interfaces作為參數(shù)僚饭,以生成key。
proxyClassCache.get
讓我們回到最初的proxyClassCache.get(loader, interfaces)代碼處,點(diǎn)擊進(jìn)去查看源碼如下:
public V get(K key, P parameter) {
Objects.requireNonNull(parameter);
expungeStaleEntries();
Object cacheKey = CacheKey.valueOf(key, refQueue);
// lazily install the 2nd level valuesMap for the particular cacheKey
ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);
if (valuesMap == null) {
ConcurrentMap<Object, Supplier<V>> oldValuesMap
= map.putIfAbsent(cacheKey,
valuesMap = new ConcurrentHashMap<>());
if (oldValuesMap != null) {
valuesMap = oldValuesMap;
}
}
// create subKey and retrieve the possible Supplier<V> stored by that
// subKey from valuesMap
Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
Supplier<V> supplier = valuesMap.get(subKey);
Factory factory = null;
while (true) {
if (supplier != null) {
// supplier might be a Factory or a CacheValue<V> instance
V value = supplier.get();
if (value != null) {
return value;
}
}
// else no supplier in cache
// or a supplier that returned null (could be a cleared CacheValue
// or a Factory that wasn't successful in installing the CacheValue)
// lazily construct a Factory
if (factory == null) {
factory = new Factory(key, parameter, subKey, valuesMap);
}
if (supplier == null) {
supplier = valuesMap.putIfAbsent(subKey, factory);
if (supplier == null) {
// successfully installed Factory
supplier = factory;
}
// else retry with winning supplier
} else {
if (valuesMap.replace(subKey, supplier, factory)) {
// successfully replaced
// cleared CacheEntry / unsuccessful Factory
// with our Factory
supplier = factory;
} else {
// retry with current supplier
supplier = valuesMap.get(subKey);
}
}
}
}
該方法入?yún)⑹莐ey與parameter岛宦,即我們傳入的classLoader與interfaces台丛。首先看的是下面兩行代碼:
Object cacheKey = CacheKey.valueOf(key, refQueue);
ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);
WeakCache類會首先查看緩存中有沒有計(jì)算過的subkey,如果沒有的話會調(diào)用subKeyFactory.apply方法生成subKey砾肺,如下
Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
獲取到的subKey后挽霉,下一步根據(jù)subKey獲取值,即我們想要生成的代理類债沮。
但是,根據(jù)subKey還不能直接拿到想要的值本鸣,需要根據(jù)subKey獲取到生成值的工廠類疫衩,然后調(diào)用工廠類對象的apply方法才能獲取,如下:
Supplier<V> supplier = valuesMap.get(subKey);
其中supplier獲取的就是valueFactory也就是我們在Proxy類看到的ProxyClassFactory類的對象荣德,還記得這個(gè)類的apply方法嗎闷煤?該方法接收classLoader與interfaces生成代理類。忘記的話可以往前翻翻涮瞻。
這里獲取supplier是使用的懶加載的方法鲤拿,即在第一次用到時(shí)才去創(chuàng)建工廠類,即while(ture)里面的邏輯署咽。
if (factory == null) {
factory = new Factory(key, parameter, subKey, valuesMap);
}
if (supplier == null) {
supplier = valuesMap.putIfAbsent(subKey, factory);
if (supplier == null) {
// successfully installed Factory
supplier = factory;
}
// else retry with winning supplier
}
那么獲取代理類的方法是在哪里被調(diào)用的呢近顷,while(true)里面有一行代碼
if (supplier != null) {
// supplier might be a Factory or a CacheValue<V> instance
V value = supplier.get();
if (value != null) {
return value;
}
}
是調(diào)用了supplier.get()方法獲取的代理類,而supplier就是Factory對象宁否,F(xiàn)actory長什么樣呢窒升?點(diǎn)開該類,看到該類是WeakCache的內(nèi)部類慕匠,其get方法長這樣:
@Override
public synchronized V get() { // serialize access
// re-check
Supplier<V> supplier = valuesMap.get(subKey);
if (supplier != this) {
// something changed while we were waiting:
// might be that we were replaced by a CacheValue
// or were removed because of failure ->
// return null to signal WeakCache.get() to retry
// the loop
return null;
}
// else still us (supplier == this)
// create new value
V value = null;
try {
value = Objects.requireNonNull(valueFactory.apply(key, parameter));
} finally {
if (value == null) { // remove us on failure
valuesMap.remove(subKey, this);
}
}
// the only path to reach here is with non-null value
assert value != null;
// wrap value with CacheValue (WeakReference)
CacheValue<V> cacheValue = new CacheValue<>(value);
// put into reverseMap
reverseMap.put(cacheValue, Boolean.TRUE);
// try replacing us with CacheValue (this should always succeed)
if (!valuesMap.replace(subKey, this, cacheValue)) {
throw new AssertionError("Should not reach here");
}
// successfully replaced us with new CacheValue -> return the value
// wrapped by it
return value;
}
其中最重要的一段代碼是:
value = Objects.requireNonNull(valueFactory.apply(key, parameter));
該段代碼調(diào)用了valueFactory.apply方法饱须,valueFactory是什么呢?下面是valueFactory在WeakCache類的定義與初始化:
private final BiFunction<K, P, ?> subKeyFactory;
private final BiFunction<K, P, V> valueFactory;
public WeakCache(BiFunction<K, P, ?> subKeyFactory,
BiFunction<K, P, V> valueFactory) {
this.subKeyFactory = Objects.requireNonNull(subKeyFactory);
this.valueFactory = Objects.requireNonNull(valueFactory);
}
可以看到valueFactory正是我們在Proxy類中定義proxyClassCache時(shí)傳入的代理工廠類ProxyClassFactory的對象台谊。
private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
調(diào)用valueFactory.apply方法蓉媳,就是在調(diào)用ProxyClassFactory中定義的apply方法,這樣锅铅,整個(gè)調(diào)用的邏輯就都走通了酪呻。