文章已遷移至https://blog.csdn.net/chaitoudaren/article/details/104833279
前言
java動(dòng)態(tài)代理主要有2種,Jdk動(dòng)態(tài)代理、Cglib動(dòng)態(tài)代理,本文主要講解Jdk動(dòng)態(tài)代理的使用、運(yùn)行機(jī)制、以及源碼分析。當(dāng)spring沒(méi)有手動(dòng)開(kāi)啟Cglib動(dòng)態(tài)代理,即:<aop:aspectj-autoproxy proxy-target-class="true"/>或@EnableAspectJAutoProxy(proxyTargetClass = true),默認(rèn)使用的就是Jdk動(dòng)態(tài)代理。動(dòng)態(tài)代理的應(yīng)用范圍很廣,例如:日志、事務(wù)管理、緩存等。本文將模擬@Cacheable,即緩存在動(dòng)態(tài)代理中的應(yīng)用進(jìn)行講解。需要注意的是,Jdk動(dòng)態(tài)代理相比起cglib動(dòng)態(tài)代理,Jdk動(dòng)態(tài)代理的對(duì)象必須實(shí)現(xiàn)接口,否則將報(bào)錯(cuò)。我們也將帶著這個(gè)問(wèn)題在源碼分析中尋找答案
當(dāng)@Cacheable注解在方法上時(shí)
- 在方法執(zhí)行前,將調(diào)用Jdk動(dòng)態(tài)代理優(yōu)先查找Redis(或其他緩存)
- 當(dāng)緩存不存在時(shí),執(zhí)行方法,例如查詢數(shù)據(jù)庫(kù)
- 在方法執(zhí)行后,再次調(diào)用Jdk動(dòng)態(tài)代理,將結(jié)果緩存到Redis中
一、使用
步驟
- 創(chuàng)建接口UserService
- 創(chuàng)建接口實(shí)現(xiàn)類UserServiceImpl
- 創(chuàng)建Jdk動(dòng)態(tài)代理JdkCacheHandler,用于增強(qiáng)UserServiceImpl方法前后的緩存邏輯
代碼
- 創(chuàng)建接口UserService
public interface UserService {
public String getUserByName(String name);
}
- 創(chuàng)建實(shí)現(xiàn)類UserServiceImpl
public class UserServiceImpl implements UserService {
@Override
public String getUserByName(String name) {
System.out.println("從數(shù)據(jù)庫(kù)中查詢到:" + name);
return name;
}
}
- 創(chuàng)建Jdk動(dòng)態(tài)代理JdkCacheHandler
public class JdkCacheHandler implements InvocationHandler {
// 目標(biāo)類對(duì)象
private Object target;
// 獲取目標(biāo)類對(duì)象
public JdkCacheHandler(Object target) {
this.target = target;
}
// 創(chuàng)建JDK代理
public Object createJDKProxy() {
Class clazz = target.getClass();
// 創(chuàng)建JDK代理需要3個(gè)參數(shù),目標(biāo)類加載器、目標(biāo)類接口、代理類對(duì)象(即本身)
return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("查找數(shù)據(jù)庫(kù)前,在緩存中查找是否存在:" + args[0]);
// 觸發(fā)目標(biāo)類方法
Object result = method.invoke(target, args);
System.out.printf("查找數(shù)據(jù)庫(kù)后,將%s加入到緩存中\(zhòng)r\n", result);
return result;
}
}
- 創(chuàng)建測(cè)試類
public class JdkTest {
@Test
public void test() {
UserService userService = new UserServiceImpl();
JdkCacheHandler jdkCacheHandler = new JdkCacheHandler(userService);
UserService proxy = (UserService) jdkCacheHandler.createJDKProxy();
System.out.println("==========================");
proxy.getUserByName("bugpool");
System.out.println("==========================");
System.out.println(proxy.getClass());
}
}
- 輸出
==========================
查找數(shù)據(jù)庫(kù)前,在緩存中查找是否存在:bugpool
從數(shù)據(jù)庫(kù)中查詢到:bugpool
查找數(shù)據(jù)庫(kù)后,將bugpool加入到緩存中
==========================
class com.sun.proxy.$Proxy4
二、調(diào)用機(jī)制
查看$Proxy代碼
可以看到當(dāng)經(jīng)過(guò)Jdk動(dòng)態(tài)代理以后,生產(chǎn)的proxy已經(jīng)不再是UserService類型了,而是$Proxy4類型,想要了解其調(diào)用機(jī)制,得先獲取到proxy類的代碼
System.out.println(proxy.getClass());
class com.sun.proxy.$Proxy4
- 修改JVM運(yùn)行參數(shù),添加
-Dsun.misc.ProxyGenerator.saveGeneratedFiles=true
修改JVM運(yùn)行參數(shù).png
添加JVM運(yùn)行參數(shù).png -
運(yùn)行test即可在com.sun.proxy查看代碼,此時(shí)生產(chǎn)的是class,idea打開(kāi)會(huì)自動(dòng)反編譯
Proxy代碼.png - 在上方輸出中可以看到代理類是$Proxy4,至此獲取到$Proxy4的源代碼,接下去分析代理類的調(diào)用機(jī)制
public final class $Proxy4 extends Proxy implements UserService {
private static Method m1;
private static Method m3;
private static Method m2;
private static Method m0;
public $Proxy4(InvocationHandler var1) throws {
super(var1);
}
public final boolean equals(Object var1) throws {
try {
return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final String getUserByName(String var1) throws {
try {
return (String)super.h.invoke(this, m3, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final String toString() throws {
try {
return (String)super.h.invoke(this, m2, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final int hashCode() throws {
try {
return (Integer)super.h.invoke(this, m0, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m3 = Class.forName("proxy.jdk.UserService").getMethod("getUserByName", Class.forName("java.lang.String"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
調(diào)用機(jī)制
- 從proxy調(diào)用開(kāi)始
// JdkTest.java
proxy.getUserByName("bugpool");
- proxy是$Proxy4類型,因此進(jìn)入$Proxy4的getUserByName方法
// $Proxy4.class
public final class $Proxy4 extends Proxy implements UserService {
...
// 構(gòu)造器,傳入JdkCacheHandler類的對(duì)象,正是下方調(diào)用的super.h屬性
public $Proxy4(InvocationHandler var1) throws {
super(var1);
}
public final String getUserByName(String var1) throws {
try {
/**
* 調(diào)用父類的h屬性的invoke方法
* 在下面的源碼分析中,會(huì)發(fā)現(xiàn)h屬性正是JdkCacheHandler類createJDKProxy方法中所傳入的this
* Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
* 而this指代的正是JdkCacheHandler類的對(duì)象,因此最后調(diào)用的是JdkCacheHandler的invoke方法
*/
return (String)super.h.invoke(this, m3, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
...
static {
...
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m3 = Class.forName("proxy.jdk.UserService").getMethod("getUserByName", Class.forName("java.lang.String"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
...
}
}
- 因此
h.invok實(shí)際調(diào)用的正是JdkCacheHandler類的invoke方法
// JdkCacheHandler.java
public class JdkCacheHandler implements InvocationHandler {
...
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("查找數(shù)據(jù)庫(kù)前,在緩存中查找是否存在:" + args[0]);
// 觸發(fā)目標(biāo)類方法
Object result = method.invoke(target, args);
System.out.printf("查找數(shù)據(jù)庫(kù)后,將%s加入到緩存中\(zhòng)r\n", result);
return result;
}
}
- 而
method.invoke(target, args)中的method = getUserByName,target = 構(gòu)造函數(shù)傳進(jìn)來(lái)的UserServiceImpl對(duì)象,args = "bugpool"
// UserServiceImpl.java
public class UserServiceImpl implements UserService {
@Override
public String getUserByName(String name) {
System.out.println("從數(shù)據(jù)庫(kù)中查詢到:" + name);
return name;
}
}
三、源碼分析
原理
了解完Jdk動(dòng)態(tài)代理的調(diào)用機(jī)制,所有核心問(wèn)題都落在了$Proxy4類的對(duì)象proxy是如何生成的上面?即下面這句代碼上,這里先給出概述,有利于宏觀上看源碼。在開(kāi)始之前先復(fù)習(xí)一下java的運(yùn)行機(jī)制:1. 所有.java文件經(jīng)過(guò)編譯生成.class文件 2. 通過(guò)類加載器classLoad將.class中的字節(jié)碼加載到JVM中 3. 運(yùn)行
// 創(chuàng)建JDK代理
public Object createJDKProxy() {
Class clazz = target.getClass();
// 創(chuàng)建JDK代理需要3個(gè)參數(shù)
// 目標(biāo)類加載器:用于加載生成的字節(jié)碼
// 目標(biāo)類接口:用于生成字節(jié)碼,也就是說(shuō)$Proxy的生產(chǎn)僅僅需要接口數(shù)組就可以完成
// 代理類對(duì)象(即本身):用于回調(diào)invoke方法,實(shí)現(xiàn)方法的增強(qiáng)
return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
}
- 通過(guò)clazz.getInterfaces()獲取到所有接口,通過(guò)接口可以生成類似以下字節(jié)碼(注意以下給出的是代碼),細(xì)細(xì)觀察會(huì)發(fā)現(xiàn)其實(shí)各個(gè)接口方法生成的代碼都是一樣的,只有
(String)super.h.invoke(this, m3, new Object[]{var1}的m3和參數(shù)有可能是不同的。所以其實(shí)想生成$Proxy字節(jié)碼,只需要接口數(shù)組就已經(jīng)完全足夠了
public final String getUserByName(String var1) throws {
try {
return (String)super.h.invoke(this, m3, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
- 此時(shí)已經(jīng)獲取到$Proxy4.class的字節(jié)碼,但是此處的字節(jié)碼還未加載到JVM中,因此需要調(diào)用clazz.getClassLoader()傳進(jìn)來(lái)的類加載器進(jìn)行加載,并得到對(duì)應(yīng)的class,也就是$Proxy類
- 獲取$Proxy類的構(gòu)造函數(shù),該構(gòu)造函數(shù)有一個(gè)重要的參數(shù)h
- 通過(guò)反射調(diào)用$Proxy類的構(gòu)造函數(shù),
cons.newInstance(new Object[]{h});構(gòu)造函數(shù)的h正是傳入的this,也就是JdkCacheHandler類的對(duì)象 - 將反射獲取到的$Proxy對(duì)象放回
源碼分析
- 從
Proxy.newProxyInstance開(kāi)始跟蹤代碼(注:①代表上方概述的步驟1)
// JdkCacheHandler.java
// 創(chuàng)建JDK代理
public Object createJDKProxy() {
Class clazz = target.getClass();
// 創(chuàng)建JDK代理需要3個(gè)參數(shù),目標(biāo)類加載器、目標(biāo)類接口、代理類對(duì)象(即本身)
return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
}
- 跟蹤代碼newProxyInstance,這里需要注意在①②過(guò)程結(jié)束后,③④過(guò)程調(diào)用前,即
Class<?> cl = getProxyClass0(loader, intfs);結(jié)束后,cl變量一直都只是class,即$Proxy4類,并未生成對(duì)應(yīng)的對(duì)象,這里不要混淆類和對(duì)象
// Proxy.java
// loader類加載器,interfaces目標(biāo)類實(shí)現(xiàn)的所有接口,h即InvocationHandler類的對(duì)象
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
// 校驗(yàn)InvocationHandler是否為空
Objects.requireNonNull(h);
// 該目標(biāo)類實(shí)現(xiàn)的接口數(shù)組
final Class<?>[] intfs = interfaces.clone();
// 安全檢查
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}
/*
* Look up or generate the designated proxy class.
*/
// 當(dāng)緩存中存在代理類則直接獲取,否則生成代理類
// ①②步驟,核心代碼,即生成代理類字節(jié)碼以及加載都在這里進(jìn)行
Class<?> cl = getProxyClass0(loader, intfs);
/*
* Invoke its constructor with the designated invocation handler.
*/
try {
if (sm != null) {
checkNewProxyPermission(Reflection.getCallerClass(), cl);
}
// ③ 從生成的代理類中獲取構(gòu)造函數(shù)
// constructorParams = { InvocationHandler.class };
final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
if (!Modifier.isPublic(cl.getModifiers())) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
cons.setAccessible(true);
return null;
}
});
}
// ④ 調(diào)用構(gòu)造函數(shù),將InvocationHandler作為參數(shù)實(shí)例化代理對(duì)象
return cons.newInstance(new Object[]{h});
} catch (IllegalAccessException|InstantiationException e) {
throw new InternalError(e.toString(), e);
} catch (InvocationTargetException e) {
Throwable t = e.getCause();
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
} else {
throw new InternalError(t.toString(), t);
}
} catch (NoSuchMethodException e) {
throw new InternalError(e.toString(), e);
}
}
- 跟蹤
Class<?> cl = getProxyClass0(loader, intfs);
// Proxy.java
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
// 如果在類加載器中已經(jīng)存在實(shí)現(xiàn)了對(duì)應(yīng)接口的代理類,則直接返回緩存中的代理類
// 否則,通過(guò)ProxyClassFactory新建代理類
return proxyClassCache.get(loader, interfaces);
}
- 跟蹤
proxyClassCache.get(loader, interfaces);(注:Jdk動(dòng)態(tài)代理對(duì)已經(jīng)生成加載過(guò)的代理類進(jìn)行了緩存以提高性能,緩存的相關(guān)代碼不是我們關(guān)心的重點(diǎn),可以跳過(guò)相關(guān)代碼)本段代碼我們主要關(guān)心V value = supplier.get();其中supplier本質(zhì)是factory,通過(guò)new Factory(key, parameter, subKey, valuesMap)創(chuàng)建
// WeakCache.java
//K和P就是WeakCache定義中的泛型,key是類加載器,parameter是接口類數(shù)組
public V get(K key, P parameter) {
// 檢查接口數(shù)組是否為空
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));
//通過(guò)sub-key得到supplier,實(shí)質(zhì)就是factory
Supplier<V> supplier = valuesMap.get(subKey);
Factory factory = null;
while (true) {
if (supplier != null) {
// supplier might be a Factory or a CacheValue<V> instance
// ①②步驟都在這里,如果supplier不為空,則直接調(diào)用get方法返回代理類
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) {
// 創(chuàng)建對(duì)應(yīng)factory,此段代碼在死循環(huán)中,下一次supplier.get()將會(huì)獲取到代理類并退出循環(huán)
factory = new Factory(key, parameter, subKey, valuesMap);
}
if (supplier == null) {
supplier = valuesMap.putIfAbsent(subKey, factory);
if (supplier == null) {
// successfully installed Factory
// 賦值給supplier
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);
}
}
}
}
- 跟蹤
V value = supplier.get();即Factory類的get方法,這里大部分的工作還是在做校驗(yàn)和緩存,我們只關(guān)心核心邏輯valueFactory.apply(key, parameter);其中valueFactory是上一個(gè)步驟傳入的ProxyClassFactory
// Factory.java
public synchronized V get() { // serialize access
// re-check
// 再次檢查,supplier是否是當(dāng)前對(duì)象
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 {
// valueFactory 是前序傳進(jìn)來(lái)的 new ProxyClassFactory()
// ①②步驟,核心邏輯,調(diào)用valueFactory.apply生成對(duì)應(yīng)代理類并加載
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;
}
- 跟蹤核心邏輯
- Jdk動(dòng)態(tài)代理通過(guò)拼湊的方式拼湊出$Proxy的全類名:com.sun.proxy.$proxy0.class
- ③生產(chǎn)字節(jié)碼
byte[] proxyClassFile = ProxyGenerator.generateProxyClass( proxyName, interfaces, accessFlags);可以看出Jdk動(dòng)態(tài)代理需要interfaces接口數(shù)組進(jìn)行生成字節(jié)碼,這也是文章開(kāi)頭提出為什么必須實(shí)現(xiàn)接口的原因。同時(shí)從參數(shù)也可以看出需要生成字節(jié)碼其實(shí)只需要接口數(shù)組,不需要其他信息。其實(shí)實(shí)現(xiàn)原理大概也可以猜出,Jdk動(dòng)態(tài)代理通過(guò)遍歷所有接口方法,為方法生成對(duì)應(yīng)的return (String)super.h.invoke(this, m0~n, new Object[]{var1});代碼 - ④加載字節(jié)碼:在③中獲取到了字節(jié)碼的字節(jié)數(shù)組,接下去就是調(diào)用classLoader將所有的字節(jié)碼讀入到JVM中
// ProxyClassFactory.java
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
// 代理類計(jì)數(shù)器
private static final AtomicLong nextUniqueNumber = new AtomicLong();
@Override
public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
// 校驗(yàn)代理類接口
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.
*/
// 當(dāng)接口修飾符是public,則所有包都可以使用
// 當(dāng)接口是非public,則生成的代理類必須和接口在與非public接口同一個(gè)包下
// 如果非public的接口均在同一個(gè)包下,則生成的代理類放在非public接口同一個(gè)包下
// 而如果非public的接口存在多個(gè),且在不同包下,則拋出異常
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
// 如果都是公有的接口,則代理類默認(rèn)放在com.sun.proxy package
proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
}
/*
* Choose a name for the proxy class to generate.
*/
// 生成計(jì)數(shù)器,例如$proxy0~n
long num = nextUniqueNumber.getAndIncrement();
// 代理類名,com.sun.proxy.$proxy0.class
String proxyName = proxyPkg + proxyClassNamePrefix + num;
/*
* Generate the specified proxy class.
*/
// ③生成代理類字節(jié)碼
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces, accessFlags);
try {
// ④使用傳進(jìn)來(lái)的classLoader將代理類字節(jié)碼加載到JVM中
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());
}
}
}


