1. 圖解
上圖主要描述了Cglib動態代理的主要執行過程,下面做詳細分析,以下原始碼使用的Cglib版本為3.2.12。
2. Enhancer原始碼分析
public Object create() {
// 判斷是否需要建立物件,false表示需要建立物件
classOnly = false;
// 使用的是無參建構函式,引數為null
argumentTypes = null;
// 建立動態代理class的方法
return createHelper();
}
...//此處省略
private Object createHelper() {
// 檢查CallBack的型別是否符合要求
preValidate();
// 建立唯一標識
Object key = KEY_FACTORY.newInstance((superclass != null) ? superclass.getName() : null,
ReflectUtils.getNames(interfaces),
filter == ALL_ZERO ? null : new WeakCacheKey<CallbackFilter>(filter),
callbackTypes,
useFactory,
interceptDuringConstruction,
serialVersionUID);
this.currentKey = key;
// 呼叫父類建立物件
Object result = super.create(key);
return result;
}
使用唯一標識key,用來建立生成唯一的動態代理類,然後將建立的工作委託給父類進行,下面分析父類AbstractClassGenerator的create方法。
3. AbstractClassGenerator原始碼分析
protected Object create(Object key) {
try {
// 獲取類載入器
ClassLoader loader = getClassLoader();
// 應用快取,其中key為類載入器,value通過該classloader載入的動態代理類
Map<ClassLoader, ClassLoaderData> cache = CACHE;
ClassLoaderData data = cache.get(loader);
if (data == null) {
synchronized (AbstractClassGenerator.class) {
cache = CACHE;
data = cache.get(loader);
if (data == null) {
Map<ClassLoader, ClassLoaderData> newCache = new WeakHashMap<ClassLoader, ClassLoaderData>(cache);
data = new ClassLoaderData(loader);
newCache.put(loader, data);
CACHE = newCache;
}
}
}
this.key = key;
// 獲取快取物件
Object obj = data.get(this, getUseCache());
// 如果返回的是Class物件,則建立一個該Class類的例項
if (obj instanceof Class) {
return firstInstance((Class) obj);
}
// 如果從快取獲取的是EnhancerFactoryData物件,那麼說明已經存在一個相應的動態代理Class物件
return nextInstance(obj);
} catch (RuntimeException e) {
throw e;
} catch (Error e) {
throw e;
} catch (Exception e) {
throw new CodeGenerationException(e);
}
}
下面進入data.get()
public Object get(AbstractClassGenerator gen, boolean useCache) {
// 如果useCache為false,表示未使用快取
if (!useCache) {
// 傳入ClassLoaderData這個內部類的當前物件
return gen.generate(ClassLoaderData.this);
} else {
// 如果useCache為true,表示使用快取
Object cachedValue = generatedClasses.get(gen);
return gen.unwrapCachedValue(cachedValue);
}
}
從原始碼可以看出,若未使用快取,則呼叫gen.generate方法,若使用快取呼叫generatedClasses.get。下面會依次分析,先分析gen.generate
protected Class generate(ClassLoaderData data) {
Class gen;
Object save = CURRENT.get();
CURRENT.set(this);
try {
// 獲取類載入
ClassLoader classLoader = data.getClassLoader();
if (classLoader == null) {
throw new IllegalStateException("ClassLoader is null while trying to define class " +
getClassName() + ". It seems that the loader has been expired from a weak reference somehow. " +
"Please file an issue at cglib's issue tracker.");
}
synchronized (classLoader) {
// 生成動態代理類的類名
String name = generateClassName(data.getUniqueNamePredicate());
data.reserveName(name);
this.setClassName(name);
}
if (attemptLoad) {
try {
gen = classLoader.loadClass(getClassName());
return gen;
} catch (ClassNotFoundException e) {
// ignore
}
}
// 使用策略模式生成位元組碼
byte[] b = strategy.generate(this);
// 獲取生成的動態代理類的類名
String className = ClassNameReader.getClassName(new ClassReader(b));
ProtectionDomain protectionDomain = getProtectionDomain();
synchronized (classLoader) { // just in case
if (protectionDomain == null) {
gen = ReflectUtils.defineClass(className, b, classLoader);
} else {
// 通過classloader載入類位元組碼,返回一個Class物件
gen = ReflectUtils.defineClass(className, b, classLoader, protectionDomain);
}
}
// 返回生成的Class物件
return gen;
} catch (RuntimeException e) {
throw e;
} catch (Error e) {
throw e;
} catch (Exception e) {
throw new CodeGenerationException(e);
} finally {
CURRENT.set(save);
}
}
上面程式碼中有個核心方法,strategy.generate,預設會進入DefaultGeneratorStrategy的generate方法
public byte[] generate(ClassGenerator cg) throws Exception {
// 獲取ClassWriter
DebuggingClassWriter cw = getClassVisitor();
// 通過ClassWriter,生成一個代理類的Class檔案
transform(cg).generateClass(cw);
// 將代理類的Class檔案轉換成位元組陣列
return transform(cw.toByteArray());
}
上述程式碼中,generateClass方法生成Class檔案是底層核心實現,通過ASM框架,完成類的Class物件的組裝,預設走KeyFactory類的generateClass。
public void generateClass(ClassVisitor v) {
ClassEmitter ce = new ClassEmitter(v);
Method newInstance = ReflectUtils.findNewInstance(keyInterface);
if (!newInstance.getReturnType().equals(Object.class)) {
throw new IllegalArgumentException("newInstance method must return Object");
}
Type[] parameterTypes = TypeUtils.getTypes(newInstance.getParameterTypes());
// 開始生成類的基本資訊,包含Class版本號、訪問許可權、Class名字等
ce.begin_class(Constants.V1_2,
Constants.ACC_PUBLIC,
getClassName(),
KEY_FACTORY,
new Type[]{ Type.getType(keyInterface) },
Constants.SOURCE_FILE);
EmitUtils.null_constructor(ce);
EmitUtils.factory_method(ce, ReflectUtils.getSignature(newInstance));
int seed = 0;
// 生成代理類的方法
CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC,
TypeUtils.parseConstructor(parameterTypes),
null);
e.load_this();
e.super_invoke_constructor();
e.load_this();
List<FieldTypeCustomizer> fieldTypeCustomizers = getCustomizers(FieldTypeCustomizer.class);
for (int i = 0; i < parameterTypes.length; i++) {
Type parameterType = parameterTypes[i];
Type fieldType = parameterType;
for (FieldTypeCustomizer customizer : fieldTypeCustomizers) {
fieldType = customizer.getOutType(i, fieldType);
}
seed += fieldType.hashCode();
ce.declare_field(Constants.ACC_PRIVATE | Constants.ACC_FINAL,
getFieldName(i),
fieldType,
null);
e.dup();
e.load_arg(i);
for (FieldTypeCustomizer customizer : fieldTypeCustomizers) {
customizer.customize(e, i, parameterType);
}
e.putfield(getFieldName(i));
}
e.return_value();
e.end_method();
// 生成代理類的hashcode方法
e = ce.begin_method(Constants.ACC_PUBLIC, HASH_CODE, null);
int hc = (constant != 0) ? constant : PRIMES[(int)(Math.abs(seed) % PRIMES.length)];
int hm = (multiplier != 0) ? multiplier : PRIMES[(int)(Math.abs(seed * 13) % PRIMES.length)];
e.push(hc);
for (int i = 0; i < parameterTypes.length; i++) {
e.load_this();
e.getfield(getFieldName(i));
EmitUtils.hash_code(e, parameterTypes[i], hm, customizers);
}
e.return_value();
e.end_method();
// 生成代理類的equals方法
e = ce.begin_method(Constants.ACC_PUBLIC, EQUALS, null);
Label fail = e.make_label();
e.load_arg(0);
e.instance_of_this();
e.if_jump(e.EQ, fail);
for (int i = 0; i < parameterTypes.length; i++) {
e.load_this();
e.getfield(getFieldName(i));
e.load_arg(0);
e.checkcast_this();
e.getfield(getFieldName(i));
EmitUtils.not_equals(e, parameterTypes[i], fail, customizers);
}
e.push(1);
e.return_value();
e.mark(fail);
e.push(0);
e.return_value();
e.end_method();
// 生成代理類的toString方法
e = ce.begin_method(Constants.ACC_PUBLIC, TO_STRING, null);
e.new_instance(Constants.TYPE_STRING_BUFFER);
e.dup();
e.invoke_constructor(Constants.TYPE_STRING_BUFFER);
for (int i = 0; i < parameterTypes.length; i++) {
if (i > 0) {
e.push(", ");
e.invoke_virtual(Constants.TYPE_STRING_BUFFER, APPEND_STRING);
}
e.load_this();
e.getfield(getFieldName(i));
EmitUtils.append_string(e, parameterTypes[i], EmitUtils.DEFAULT_DELIMITERS, customizers);
}
e.invoke_virtual(Constants.TYPE_STRING_BUFFER, TO_STRING);
e.return_value();
e.end_method();
// 生成代理類結束
ce.end_class();
}
通過分析上述程式碼,得知代理類的Class位元組碼檔案生成是由底層的ClassEmitter封裝ASM框架完成的,關於ASM框架,將在下一講繼續深入,裡面涉及到三種設計模式的具體應用。
如果使用快取方式獲取代理類的Class物件,會呼叫generatedClasses.get,進入方法會到LoadingCache中
public V get(K key) {
final KK cacheKey = keyMapper.apply(key);
Object v = map.get(cacheKey);
if (v != null && !(v instanceof FutureTask)) {
return (V) v;
}
return createEntry(key, cacheKey, v);
}
進入createEntry
protected V createEntry(final K key, KK cacheKey, Object v) {
FutureTask<V> task;
boolean creator = false;
if (v != null) {
// Another thread is already loading an instance
task = (FutureTask<V>) v;
} else {
task = new FutureTask<V>(new Callable<V>() {
public V call() throws Exception {
return loader.apply(key);
}
});
Object prevTask = map.putIfAbsent(cacheKey, task);
if (prevTask == null) {
// creator does the load
creator = true;
task.run();
} else if (prevTask instanceof FutureTask) {
task = (FutureTask<V>) prevTask;
} else {
return (V) prevTask;
}
}
上面程式碼會呼叫task.run,進入執行緒loader.apply方法,最終進入AbstractClassGenerator的內部類ClassLoaderData的方法
public ClassLoaderData(ClassLoader classLoader) {
if (classLoader == null) {
throw new IllegalArgumentException("classLoader == null is not yet supported");
}
this.classLoader = new WeakReference<ClassLoader>(classLoader);
Function<AbstractClassGenerator, Object> load =
new Function<AbstractClassGenerator, Object>() {
public Object apply(AbstractClassGenerator gen) {
Class klass = gen.generate(ClassLoaderData.this);
return gen.wrapCachedClass(klass);
}
};
generatedClasses = new LoadingCache<AbstractClassGenerator, Object, Object>(GET_KEY, load);
}
會發現,匿名內部類裡面還是會呼叫上面程式碼分析過的gen.generate方法,最終通過位元組碼框架ASM生成Class物件。
3. 逐步除錯解析
整個除錯過程從【趣味設計模式系列】之【代理模式1-基本原理、實戰及框架應用】中的CglibTest示例程式開始除錯,下面除錯過程會比較長,總共分三個階段。
3.1 初始化Enhancer例項階段
進入CglibProxy的createProxy方法,如下圖
當執行到13行時,會初始化父類AbstractClassGenerator的靜態常量值DEFAULT_USE_CACHE,該值預設為true,如下圖
接著會初始化Enhancer的靜態常量KEY_FACTORY,該值也是建立EnhancerKey物件的關鍵,如下圖
隨後進入KeyFactory的create方法
上述方法裡面會呼叫gen.create
繼續呼叫靜態內部類Generator的create方法,介面名為interface net.sf.cglib.proxy.Enhancer$EnhancerKey
隨後呼叫super.create,進入父類AbstractClassGenerator的create方法
再往下會優先從快取取資料
進入data.get方法
預設useCache為true,會走else邏輯,隨後會進入LoadingCache的get方法
上面程式碼34行,會執行createEntry,進入LoadingCache類52行的task執行緒中,61行執行緒執行run方法,會執行執行緒內部call的方法,呼叫loader.apply
再往下會走到AbstractClassGenerator的96行
進入generate方法
再走到320行,進入generateClassName方法,執行生成類名的方法
隨後又回到AbstractClassGenerator,執行332行
進入預設位元組碼生成策略類DefaultGeneratorStrategy的generate方法
執行到25行,進入KeyFactory類的generatorClass方法
上述程式碼,從241行開始,通過ASM框架生成新的類
通過觀察類名,ce下面的classinfo資訊,看出生成類名為net.sf.cglib.proxy.Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$7fb24d72
的類,
最後又回到AbstractClassGenerator類的296行,用生成的Class物件,通過反射生成上述類名為net.sf.cglib.proxy.Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$7fb24d72
的
例項
以上步驟都是在執行Enhancer enhancer = new Enhancer()
這一步完成的,總結上述步驟,就是為建立的代理類生成一個唯一的key,該key又由KeyFactory生成,最終生成的key是類名為net.sf.cglib.proxy.Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$7fb24d72
的類。
3.2 代理類生成階段
下面繼續調式,走到CglibProxy的18行,開始執行enhancer.create方法,真正建立代理類,見下圖
進入Enhancer的create方法,執行到305行
再進入createHelper方法
發現key為之前生成的類名為net.sf.cglib.proxy.Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$7fb24d72
的例項,屬性裡面包含若干屬性物件,其中FIELD_0為com.wzj.cglib.Apple,FIELD_3為回撥型別陣列,陣列裡只有一個元素,值為Lnet/sf/cglib/proxy/MethodInterceptor,再往下繼續走,480行會呼叫父類的create方法,進入又回到之前AbstractClassGenerator類的create方法
執行到294行,從快取獲取值
進入get方法
繼續走else邏輯,再進入get方法,走入34行的createEntry方法
一直往下走,發現除錯步驟與上述一致,中間省去部分步驟,走到代理類的預設命名策略,名字為com.wzj.cglib.Apple$$EnhancerByCGLIB$$3a0529f7
隨後往下幾步與上述一致,最終在生成類的Class檔案時,與上述稍有不同,會走到Enhancer類的generateClass方法
繼續往下走,569行有幾句註釋,執行順序非常重要,必須先新增父類,以及它的父類鏈,然後每個介面以及父類介面,隨後按照註釋說明,到575行,執行getMethods方法,見下圖
進入getMethods方法,執行到551行,進入MethodWrapper.createSet方法
首先會進入靜態常量方法包裝類的key對應類MethodWrapperKey的例項初始化,如下圖
隨後進入KeyFactory的create方法
往下221行,執行super.create方法
進入該方法,又會回到最初的AbstractClassGenerator的create方法,
再往下與上面除錯過的過程類似,中間部分除錯省略,最後生成代理類Class檔案,如下圖
最後回到AbstractClassGenerator類的298行,nextInstance生成代理類的例項
最終通過設定回撥函式,並通過反射完成代理類的例項的初始化,如下圖
3.3 代理類的方法執行階段
進入自定義的intercept方法
進入invokeSuper方法
執行到init方法
進入init的74行
進入helper方法,執行121的create方法
進入create方法,回到AbstractClassGenerator的create方法
根據ci得到該方法的被代理類,代理類,分別生成FastClass的兩個例項f1,f2,下圖是f1的生成過程
同理,生成FastClass的例項f2
目的是計算被代理類與代理類各自的方法的索引,獲取當前方法在f1,f2中的簽名,得到一個index,可以根據index對映對應類的對應方法,因此方法名->簽名->索引值,三者是一一對應關係。
init方法完成後,往下走到228行,這裡通過呼叫代理類的索引值19對應的方法,取代反射
進入會走到被代理類的目標方法
至此,上面代理的全過程已經分析完畢。
4. FastClass原始碼解析
上述除錯過程中,生成了兩個FastClass的例項,分別是被代理類與代理類的在執行代理方法時建立,這裡應用了一個懶載入的思想,也就是說,一開始並沒有FastClass,只有當MethodProxy方法代理真正被請求的時候,被代理類的方法需要對映到代理類的方法時,為了避免過度使用反射,才生成了FastClass的例項,完成呼叫。
FastClass有兩個主要方法,獲取方法簽名後的索引值,以及根據索引值呼叫方法,主要思想就是在為了避免方法呼叫時,過度使用反射造成呼叫慢的問題,下面是兩個方法。
//方法簽名後的索引值
abstract public int getIndex(Signature sig);
//根據索引值呼叫方法
abstract public Object invoke(int index, Object obj, Object[] args)
示例程式跑完後會在專案的根目錄下生成三個類,其中兩個FastClass類,一個代理類,如圖
Apple$$FastClassByCGLIB$$ca2d2eb9類是為了使用被代理類的方法索引而生成的
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package com.wzj.cglib;
import java.lang.reflect.InvocationTargetException;
import net.sf.cglib.core.Signature;
import net.sf.cglib.reflect.FastClass;
public class Apple$$FastClassByCGLIB$$ca2d2eb9 extends FastClass {
public Apple$$FastClassByCGLIB$$ca2d2eb9(Class var1) {
super(var1);
}
public int getIndex(Signature var1) {
String var10000 = var1.toString();
switch(var10000.hashCode()) {
case -1596601914:
// 當方法為secKill時,索引為0
if (var10000.equals("secKill()V")) {
return 0;
}
break;
case 1826985398:
if (var10000.equals("equals(Ljava/lang/Object;)Z")) {
return 1;
}
break;
case 1913648695:
if (var10000.equals("toString()Ljava/lang/String;")) {
return 2;
}
break;
case 1984935277:
if (var10000.equals("hashCode()I")) {
return 3;
}
}
return -1;
}
public int getIndex(String var1, Class[] var2) {
switch(var1.hashCode()) {
case -1776922004:
if (var1.equals("toString")) {
switch(var2.length) {
case 0:
return 2;
}
}
break;
case -1295482945:
if (var1.equals("equals")) {
switch(var2.length) {
case 1:
if (var2[0].getName().equals("java.lang.Object")) {
return 1;
}
}
}
break;
case 147696667:
if (var1.equals("hashCode")) {
switch(var2.length) {
case 0:
return 3;
}
}
break;
case 1969019727:
if (var1.equals("secKill")) {
switch(var2.length) {
case 0:
return 0;
}
}
}
return -1;
}
public int getIndex(Class[] var1) {
switch(var1.length) {
case 0:
return 0;
default:
return -1;
}
}
public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {
Apple var10000 = (Apple)var2;
int var10001 = var1;
try {
switch(var10001) {
case 0:
var10000.secKill();
return null;
case 1:
return new Boolean(var10000.equals(var3[0]));
case 2:
return var10000.toString();
case 3:
return new Integer(var10000.hashCode());
}
} catch (Throwable var4) {
throw new InvocationTargetException(var4);
}
throw new IllegalArgumentException("Cannot find matching method/constructor");
}
public Object newInstance(int var1, Object[] var2) throws InvocationTargetException {
Apple var10000 = new Apple;
Apple var10001 = var10000;
int var10002 = var1;
try {
switch(var10002) {
case 0:
var10001.<init>();
return var10000;
}
} catch (Throwable var3) {
throw new InvocationTargetException(var3);
}
throw new IllegalArgumentException("Cannot find matching method/constructor");
}
public int getMaxIndex() {
return 3;
}
}
Apple$$EnhancerByCGLIB$$3a0529f7$$FastClassByCGLIB$$17333818類是為了使用代理類的方法索引而生成的,見下圖
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package com.wzj.cglib;
import com.wzj.cglib.Apple..EnhancerByCGLIB..3a0529f7;
import java.lang.reflect.InvocationTargetException;
import net.sf.cglib.core.Signature;
import net.sf.cglib.proxy.Callback;
import net.sf.cglib.reflect.FastClass;
public class Apple$$EnhancerByCGLIB$$3a0529f7$$FastClassByCGLIB$$17333818 extends FastClass {
public Apple$$EnhancerByCGLIB$$3a0529f7$$FastClassByCGLIB$$17333818(Class var1) {
super(var1);
}
public int getIndex(Signature var1) {
String var10000 = var1.toString();
switch(var10000.hashCode()) {
case -2055565910:
if (var10000.equals("CGLIB$SET_THREAD_CALLBACKS([Lnet/sf/cglib/proxy/Callback;)V")) {
return 17;
}
break;
case -1882565338:
if (var10000.equals("CGLIB$equals$1(Ljava/lang/Object;)Z")) {
return 9;
}
break;
case -1596601914:
if (var10000.equals("secKill()V")) {
return 7;
}
break;
case -1457535688:
if (var10000.equals("CGLIB$STATICHOOK1()V")) {
return 14;
}
break;
case -1411842725:
if (var10000.equals("CGLIB$hashCode$3()I")) {
return 8;
}
break;
case -894172689:
if (var10000.equals("newInstance(Lnet/sf/cglib/proxy/Callback;)Ljava/lang/Object;")) {
return 6;
}
break;
case -623122092:
if (var10000.equals("CGLIB$findMethodProxy(Lnet/sf/cglib/core/Signature;)Lnet/sf/cglib/proxy/MethodProxy;")) {
return 20;
}
break;
case -508378822:
if (var10000.equals("clone()Ljava/lang/Object;")) {
return 3;
}
break;
case -419626537:
if (var10000.equals("setCallbacks([Lnet/sf/cglib/proxy/Callback;)V")) {
return 15;
}
break;
case -266769987:
if (var10000.equals("CGLIB$secKill$0()V")) {
return 12;
}
break;
case 560567118:
if (var10000.equals("setCallback(ILnet/sf/cglib/proxy/Callback;)V")) {
return 13;
}
break;
case 811063227:
if (var10000.equals("newInstance([Ljava/lang/Class;[Ljava/lang/Object;[Lnet/sf/cglib/proxy/Callback;)Ljava/lang/Object;")) {
return 5;
}
break;
case 973717575:
if (var10000.equals("getCallbacks()[Lnet/sf/cglib/proxy/Callback;")) {
return 18;
}
break;
case 1221173700:
if (var10000.equals("newInstance([Lnet/sf/cglib/proxy/Callback;)Ljava/lang/Object;")) {
return 4;
}
break;
case 1230699260:
if (var10000.equals("getCallback(I)Lnet/sf/cglib/proxy/Callback;")) {
return 19;
}
break;
case 1306468936:
if (var10000.equals("CGLIB$toString$2()Ljava/lang/String;")) {
return 11;
}
break;
case 1584330438:
if (var10000.equals("CGLIB$SET_STATIC_CALLBACKS([Lnet/sf/cglib/proxy/Callback;)V")) {
return 16;
}
break;
case 1800494055:
if (var10000.equals("CGLIB$clone$4()Ljava/lang/Object;")) {
return 10;
}
break;
case 1826985398:
if (var10000.equals("equals(Ljava/lang/Object;)Z")) {
return 0;
}
break;
case 1913648695:
if (var10000.equals("toString()Ljava/lang/String;")) {
return 1;
}
break;
case 1984935277:
if (var10000.equals("hashCode()I")) {
return 2;
}
}
return -1;
}
public int getIndex(String var1, Class[] var2) {
switch(var1.hashCode()) {
case -1776922004:
if (var1.equals("toString")) {
switch(var2.length) {
case 0:
return 1;
}
}
break;
case -1295482945:
if (var1.equals("equals")) {
switch(var2.length) {
case 1:
if (var2[0].getName().equals("java.lang.Object")) {
return 0;
}
}
}
break;
case -1053468136:
if (var1.equals("getCallbacks")) {
switch(var2.length) {
case 0:
return 18;
}
}
break;
case -124978609:
if (var1.equals("CGLIB$equals$1")) {
switch(var2.length) {
case 1:
if (var2[0].getName().equals("java.lang.Object")) {
return 9;
}
}
}
break;
case -60403779:
if (var1.equals("CGLIB$SET_STATIC_CALLBACKS")) {
switch(var2.length) {
case 1:
if (var2[0].getName().equals("[Lnet.sf.cglib.proxy.Callback;")) {
return 16;
}
}
}
break;
case -29025555:
if (var1.equals("CGLIB$hashCode$3")) {
switch(var2.length) {
case 0:
return 8;
}
}
break;
case 85179481:
if (var1.equals("CGLIB$SET_THREAD_CALLBACKS")) {
switch(var2.length) {
case 1:
if (var2[0].getName().equals("[Lnet.sf.cglib.proxy.Callback;")) {
return 17;
}
}
}
break;
case 94756189:
if (var1.equals("clone")) {
switch(var2.length) {
case 0:
return 3;
}
}
break;
case 147696667:
if (var1.equals("hashCode")) {
switch(var2.length) {
case 0:
return 2;
}
}
break;
case 161998109:
if (var1.equals("CGLIB$STATICHOOK1")) {
switch(var2.length) {
case 0:
return 14;
}
}
break;
case 495524492:
if (var1.equals("setCallbacks")) {
switch(var2.length) {
case 1:
if (var2[0].getName().equals("[Lnet.sf.cglib.proxy.Callback;")) {
return 15;
}
}
}
break;
case 1154623345:
if (var1.equals("CGLIB$findMethodProxy")) {
switch(var2.length) {
case 1:
if (var2[0].getName().equals("net.sf.cglib.core.Signature")) {
return 20;
}
}
}
break;
case 1543336189:
if (var1.equals("CGLIB$toString$2")) {
switch(var2.length) {
case 0:
return 11;
}
}
break;
case 1811874389:
if (var1.equals("newInstance")) {
switch(var2.length) {
case 1:
String var10001 = var2[0].getName();
switch(var10001.hashCode()) {
case -845341380:
if (var10001.equals("net.sf.cglib.proxy.Callback")) {
return 6;
}
break;
case 1730110032:
if (var10001.equals("[Lnet.sf.cglib.proxy.Callback;")) {
return 4;
}
}
case 2:
default:
break;
case 3:
if (var2[0].getName().equals("[Ljava.lang.Class;") && var2[1].getName().equals("[Ljava.lang.Object;") && var2[2].getName().equals("[Lnet.sf.cglib.proxy.Callback;")) {
return 5;
}
}
}
break;
case 1817099975:
if (var1.equals("setCallback")) {
switch(var2.length) {
case 2:
if (var2[0].getName().equals("int") && var2[1].getName().equals("net.sf.cglib.proxy.Callback")) {
return 13;
}
}
}
break;
case 1905679803:
if (var1.equals("getCallback")) {
switch(var2.length) {
case 1:
if (var2[0].getName().equals("int")) {
return 19;
}
}
}
break;
case 1951977610:
if (var1.equals("CGLIB$clone$4")) {
switch(var2.length) {
case 0:
return 10;
}
}
break;
case 1969019727:
if (var1.equals("secKill")) {
switch(var2.length) {
case 0:
return 7;
}
}
break;
case 2019235512:
// 呼叫CGLIB$secKill$0()時,返回索引值12
if (var1.equals("CGLIB$secKill$0")) {
switch(var2.length) {
case 0:
return 12;
}
}
}
return -1;
}
public int getIndex(Class[] var1) {
switch(var1.length) {
case 0:
return 0;
default:
return -1;
}
}
public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {
3a0529f7 var10000 = (3a0529f7)var2;
int var10001 = var1;
try {
switch(var10001) {
case 0:
return new Boolean(var10000.equals(var3[0]));
case 1:
return var10000.toString();
case 2:
return new Integer(var10000.hashCode());
case 3:
return var10000.clone();
case 4:
return var10000.newInstance((Callback[])var3[0]);
case 5:
return var10000.newInstance((Class[])var3[0], (Object[])var3[1], (Callback[])var3[2]);
case 6:
return var10000.newInstance((Callback)var3[0]);
case 7:
var10000.secKill();
return null;
case 8:
return new Integer(var10000.CGLIB$hashCode$3());
case 9:
return new Boolean(var10000.CGLIB$equals$1(var3[0]));
case 10:
return var10000.CGLIB$clone$4();
case 11:
return var10000.CGLIB$toString$2();
// 當計算index為12時,呼叫var10000.CGLIB$secKill$0()
case 12:
var10000.CGLIB$secKill$0();
return null;
case 13:
var10000.setCallback(((Number)var3[0]).intValue(), (Callback)var3[1]);
return null;
case 14:
3a0529f7.CGLIB$STATICHOOK1();
return null;
case 15:
var10000.setCallbacks((Callback[])var3[0]);
return null;
case 16:
3a0529f7.CGLIB$SET_STATIC_CALLBACKS((Callback[])var3[0]);
return null;
case 17:
3a0529f7.CGLIB$SET_THREAD_CALLBACKS((Callback[])var3[0]);
return null;
case 18:
return var10000.getCallbacks();
case 19:
return var10000.getCallback(((Number)var3[0]).intValue());
case 20:
return 3a0529f7.CGLIB$findMethodProxy((Signature)var3[0]);
}
} catch (Throwable var4) {
throw new InvocationTargetException(var4);
}
throw new IllegalArgumentException("Cannot find matching method/constructor");
}
public Object newInstance(int var1, Object[] var2) throws InvocationTargetException {
3a0529f7 var10000 = new 3a0529f7;
3a0529f7 var10001 = var10000;
int var10002 = var1;
try {
switch(var10002) {
case 0:
var10001.<init>();
return var10000;
}
} catch (Throwable var3) {
throw new InvocationTargetException(var3);
}
throw new IllegalArgumentException("Cannot find matching method/constructor");
}
public int getMaxIndex() {
return 20;
}
}
代理類為Apple$$EnhancerByCGLIB$$3a0529f7,如下圖,當下面的CGLIB$secKill$0方法被呼叫時,父類的super.secKill被執行
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package com.wzj.cglib;
import java.lang.reflect.Method;
import net.sf.cglib.core.ReflectUtils;
import net.sf.cglib.core.Signature;
import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.Factory;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class Apple$$EnhancerByCGLIB$$3a0529f7 extends Apple implements Factory {
private boolean CGLIB$BOUND;
public static Object CGLIB$FACTORY_DATA;
private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
private static final Callback[] CGLIB$STATIC_CALLBACKS;
private MethodInterceptor CGLIB$CALLBACK_0;
private static Object CGLIB$CALLBACK_FILTER;
private static final Method CGLIB$secKill$0$Method;
private static final MethodProxy CGLIB$secKill$0$Proxy;
private static final Object[] CGLIB$emptyArgs;
private static final Method CGLIB$equals$1$Method;
private static final MethodProxy CGLIB$equals$1$Proxy;
private static final Method CGLIB$toString$2$Method;
private static final MethodProxy CGLIB$toString$2$Proxy;
private static final Method CGLIB$hashCode$3$Method;
private static final MethodProxy CGLIB$hashCode$3$Proxy;
private static final Method CGLIB$clone$4$Method;
private static final MethodProxy CGLIB$clone$4$Proxy;
static void CGLIB$STATICHOOK1() {
CGLIB$THREAD_CALLBACKS = new ThreadLocal();
CGLIB$emptyArgs = new Object[0];
Class var0 = Class.forName("com.wzj.cglib.Apple$$EnhancerByCGLIB$$3a0529f7");
Class var1;
CGLIB$secKill$0$Method = ReflectUtils.findMethods(new String[]{"secKill", "()V"}, (var1 = Class.forName("com.wzj.cglib.Apple")).getDeclaredMethods())[0];
CGLIB$secKill$0$Proxy = MethodProxy.create(var1, var0, "()V", "secKill", "CGLIB$secKill$0");
Method[] var10000 = ReflectUtils.findMethods(new String[]{"equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;"}, (var1 = Class.forName("java.lang.Object")).getDeclaredMethods());
CGLIB$equals$1$Method = var10000[0];
CGLIB$equals$1$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$1");
CGLIB$toString$2$Method = var10000[1];
CGLIB$toString$2$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/String;", "toString", "CGLIB$toString$2");
CGLIB$hashCode$3$Method = var10000[2];
CGLIB$hashCode$3$Proxy = MethodProxy.create(var1, var0, "()I", "hashCode", "CGLIB$hashCode$3");
CGLIB$clone$4$Method = var10000[3];
CGLIB$clone$4$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/Object;", "clone", "CGLIB$clone$4");
}
// 當CGLIB$secKill$0被執行,呼叫父類被代理的方法
final void CGLIB$secKill$0() {
super.secKill();
}
// 當代理方法被執行,內部呼叫自定義intercept方法
public final void secKill() {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
if (var10000 != null) {
var10000.intercept(this, CGLIB$secKill$0$Method, CGLIB$emptyArgs, CGLIB$secKill$0$Proxy);
} else {
super.secKill();
}
}
final boolean CGLIB$equals$1(Object var1) {
return super.equals(var1);
}
public final boolean equals(Object var1) {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
if (var10000 != null) {
Object var2 = var10000.intercept(this, CGLIB$equals$1$Method, new Object[]{var1}, CGLIB$equals$1$Proxy);
return var2 == null ? false : (Boolean)var2;
} else {
return super.equals(var1);
}
}
final String CGLIB$toString$2() {
return super.toString();
}
public final String toString() {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
return var10000 != null ? (String)var10000.intercept(this, CGLIB$toString$2$Method, CGLIB$emptyArgs, CGLIB$toString$2$Proxy) : super.toString();
}
final int CGLIB$hashCode$3() {
return super.hashCode();
}
public final int hashCode() {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
if (var10000 != null) {
Object var1 = var10000.intercept(this, CGLIB$hashCode$3$Method, CGLIB$emptyArgs, CGLIB$hashCode$3$Proxy);
return var1 == null ? 0 : ((Number)var1).intValue();
} else {
return super.hashCode();
}
}
final Object CGLIB$clone$4() throws CloneNotSupportedException {
return super.clone();
}
protected final Object clone() throws CloneNotSupportedException {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
return var10000 != null ? var10000.intercept(this, CGLIB$clone$4$Method, CGLIB$emptyArgs, CGLIB$clone$4$Proxy) : super.clone();
}
public static MethodProxy CGLIB$findMethodProxy(Signature var0) {
String var10000 = var0.toString();
switch(var10000.hashCode()) {
case -1596601914:
if (var10000.equals("secKill()V")) {
return CGLIB$secKill$0$Proxy;
}
break;
case -508378822:
if (var10000.equals("clone()Ljava/lang/Object;")) {
return CGLIB$clone$4$Proxy;
}
break;
case 1826985398:
if (var10000.equals("equals(Ljava/lang/Object;)Z")) {
return CGLIB$equals$1$Proxy;
}
break;
case 1913648695:
if (var10000.equals("toString()Ljava/lang/String;")) {
return CGLIB$toString$2$Proxy;
}
break;
case 1984935277:
if (var10000.equals("hashCode()I")) {
return CGLIB$hashCode$3$Proxy;
}
}
return null;
}
public Apple$$EnhancerByCGLIB$$3a0529f7() {
CGLIB$BIND_CALLBACKS(this);
}
public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] var0) {
CGLIB$THREAD_CALLBACKS.set(var0);
}
public static void CGLIB$SET_STATIC_CALLBACKS(Callback[] var0) {
CGLIB$STATIC_CALLBACKS = var0;
}
private static final void CGLIB$BIND_CALLBACKS(Object var0) {
Apple$$EnhancerByCGLIB$$3a0529f7 var1 = (Apple$$EnhancerByCGLIB$$3a0529f7)var0;
if (!var1.CGLIB$BOUND) {
var1.CGLIB$BOUND = true;
Object var10000 = CGLIB$THREAD_CALLBACKS.get();
if (var10000 == null) {
var10000 = CGLIB$STATIC_CALLBACKS;
if (var10000 == null) {
return;
}
}
var1.CGLIB$CALLBACK_0 = (MethodInterceptor)((Callback[])var10000)[0];
}
}
public Object newInstance(Callback[] var1) {
CGLIB$SET_THREAD_CALLBACKS(var1);
Apple$$EnhancerByCGLIB$$3a0529f7 var10000 = new Apple$$EnhancerByCGLIB$$3a0529f7();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
}
public Object newInstance(Callback var1) {
CGLIB$SET_THREAD_CALLBACKS(new Callback[]{var1});
Apple$$EnhancerByCGLIB$$3a0529f7 var10000 = new Apple$$EnhancerByCGLIB$$3a0529f7();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
}
public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) {
CGLIB$SET_THREAD_CALLBACKS(var3);
Apple$$EnhancerByCGLIB$$3a0529f7 var10000 = new Apple$$EnhancerByCGLIB$$3a0529f7;
switch(var1.length) {
case 0:
var10000.<init>();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
default:
throw new IllegalArgumentException("Constructor not found");
}
}
public Callback getCallback(int var1) {
CGLIB$BIND_CALLBACKS(this);
MethodInterceptor var10000;
switch(var1) {
case 0:
var10000 = this.CGLIB$CALLBACK_0;
break;
default:
var10000 = null;
}
return var10000;
}
public void setCallback(int var1, Callback var2) {
switch(var1) {
case 0:
this.CGLIB$CALLBACK_0 = (MethodInterceptor)var2;
default:
}
}
public Callback[] getCallbacks() {
CGLIB$BIND_CALLBACKS(this);
return new Callback[]{this.CGLIB$CALLBACK_0};
}
public void setCallbacks(Callback[] var1) {
this.CGLIB$CALLBACK_0 = (MethodInterceptor)var1[0];
}
static {
CGLIB$STATICHOOK1();
}
}
5. 總結
5.1 代理的執行的三個階段
- 第一階段,生成唯一代理類需要唯一的key,key的生成又需要KeyFactory,第一階段就是初始化KeyFactory與key;
- 第二階段,生成代理類,代理類中的方法通過方法代理一併生成,其中關鍵的步驟都是在AbstractClassGenerator中完成的,並在生成過程中預設使用快取取代理,快取沒有,利用ASM框架生成;
- 第三階段,代理方法執行階段,通過FastClass生成中間類,為目標方法的執行提供方便。
5.2 FastClass機制
- 使用了懶載入思想,在執行代理方法階段生成,而非一開始就生成;
- 通過方法->簽名->索引值的對映,直接根據最終的索引值呼叫代理類方法,而非通過反射,提高效率。