通過(guò)這篇文章你會(huì)知道如下:
-
動(dòng)態(tài)代理如何實(shí)現(xiàn)盖灸?
-
代理對(duì)象與真實(shí)對(duì)象之間是什么關(guān)系旷太?
-
通過(guò)代理對(duì)象的調(diào)用,invocationHandler中的invoke方法是如何被調(diào)用的
目前尚未厘清字節(jié)碼是如何生成,代理對(duì)象中的方法體是如何寫(xiě)入的
?
動(dòng)態(tài)代理就是將代理插入到客戶和目標(biāo)之間妨托,從而為客戶和目標(biāo)對(duì)象之間引入一定的間接性发笔,這個(gè)間接性就可以給代理提供很多的活動(dòng)空間盟萨,代理可以在調(diào)用目標(biāo)對(duì)象的前后做些通知操作,從而實(shí)現(xiàn)新的功能或者擴(kuò)展目標(biāo)對(duì)象的功能了讨;
-
動(dòng)態(tài)代理常規(guī)寫(xiě)法例子:
-
調(diào)用過(guò)程分析
從上面的例子得知捻激,proxy是通過(guò)Proxy.newProxyInstance產(chǎn)生的,此時(shí)就有如下疑問(wèn):
- 調(diào)用proxy.doSomething時(shí)候前计,內(nèi)部是如何調(diào)用到invoke方法胞谭?
- 參數(shù)interface作用是啥?
下面就開(kāi)始分析這些疑問(wèn)
下面這張圖說(shuō)明男杈,代理對(duì)象是通過(guò)getProxyClass0方法產(chǎn)生的丈屹,最后通過(guò)newIntstance實(shí)例化,同時(shí)傳入invokehandler對(duì)象
Proxy.newProxyInstance
下圖說(shuō)明代理對(duì)象的產(chǎn)生最終會(huì)落到proxyClassFactory中伶棒,注釋也有說(shuō)明這點(diǎn)旺垒,但是具體為什么會(huì)落到proxyClassFactory彩库,你打個(gè)斷點(diǎn)跟蹤會(huì),自然而然就知道了袖牙。所以現(xiàn)在的重點(diǎn)就在proxyClassFactory里面是如何產(chǎn)生對(duì)象的侧巨?
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());
}
}
}
proxyClassFactory類(lèi)中可以看到代理對(duì)象產(chǎn)生的名字構(gòu)成過(guò)程,同時(shí)會(huì)處理如果實(shí)現(xiàn)的接口訪問(wèn)權(quán)限不是public的情況鞭达;
String proxyName = proxyPkg + proxyClassNamePrefix + num;
生成代理對(duì)象的過(guò)程在這段代碼里面司忱,真正產(chǎn)生隊(duì)里對(duì)象的類(lèi)是ProxyGenerator.generateClassFile方法
最終生成的代理對(duì)象如下,可以發(fā)現(xiàn)在doSomething方法中畴蹭,發(fā)現(xiàn)是調(diào)用了h.invokerhandler的invoke方法坦仍,這個(gè)h對(duì)象則是父類(lèi)Proxy中的屬性,通過(guò)構(gòu)造方法進(jìn)行對(duì)象賦值叨襟;所以就可以解釋最初的疑問(wèn)了繁扎。
另外要獲取這個(gè)對(duì)象的反編譯的源碼,需要改變sun.misc.ProxyGenerator.saveGeneratedFiles參數(shù)糊闽,才能寫(xiě)入到硬盤(pán)梳玫,具體為什么是true,在ProxyGenerator.generateProxyClass方法中可以看到原因右犹。
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
package com.sun.proxy;
import com.example.proxy.Man;
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 Man {
private static Method m1;
private static Method m3;
private static Method m2;
private static Method m0;
public $Proxy0(InvocationHandler paramInvocationHandler)
throws {
super(paramInvocationHandler);
}
public final boolean equals(Object paramObject)
throws {
try {
return ((Boolean) this.h.invoke(this, m1, new Object[]{paramObject})).booleanValue();
} catch (Error | RuntimeException localError) {
throw localError;
} catch (Throwable localThrowable) {
throw new UndeclaredThrowableException(localThrowable);
}
}
public final void doSomething()
throws {
try {
this.h.invoke(this, m3, null);
return;
} catch (Error | RuntimeException localError) {
throw localError;
} catch (Throwable localThrowable) {
throw new UndeclaredThrowableException(localThrowable);
}
}
public final String toString()
throws {
try {
return (String) this.h.invoke(this, m2, null);
} catch (Error | RuntimeException localError) {
throw localError;
} catch (Throwable localThrowable) {
throw new UndeclaredThrowableException(localThrowable);
}
}
public final int hashCode()
throws {
try {
return ((Integer) this.h.invoke(this, m0, null)).intValue();
} catch (Error | RuntimeException localError) {
throw localError;
} catch (Throwable localThrowable) {
throw new UndeclaredThrowableException(localThrowable);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[]{Class.forName("java.lang.Object")});
m3 = Class.forName("com.example.proxy.Man").getMethod("doSomething", new Class[0]);
m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
return;
} catch (NoSuchMethodException localNoSuchMethodException) {
throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
} catch (ClassNotFoundException localClassNotFoundException) {
throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
}
}
}