CGLIB 动态代理原理

案例代码

被代理类Calculator

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Calculator {
public int add(int i, int j) {
return i + j;
}

public int sub(int i, int j) {
return i - j;
}

public int mult(int i, int j) {
return i * j;
}

public int div(int i, int j) {
return i / j;
}
}

MethodInterceptor

1
2
3
4
5
6
7
public class MyCglib implements MethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("调用cglib动态代理");
return methodProxy.invokeSuper(o, objects);
}
}

程序入口

1
2
3
4
5
6
7
8
9
10
11
12
public class CglibTest {
public static void main(String[] args) {
// 设置cglib生成的class文件保存路径
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "E:\\mashibing\\spring");
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(Calculator.class);
enhancer.setCallback(new MyCglib());
Calculator myCalculator = (Calculator) enhancer.create();
myCalculator.add(1, 1);
System.out.println(myCalculator.getClass());
}
}

从add(1, 1)开始说起

代理对象的class文件

当程序运行完成之后,会在指定位置生成代理对象的class文件。为了后续讲解,这里先将生成的class文件展示。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
package com.eitan.proxy.cglib;

import java.lang.reflect.Method;
import org.springframework.cglib.core.ReflectUtils;
import org.springframework.cglib.core.Signature;
import org.springframework.cglib.proxy.Callback;
import org.springframework.cglib.proxy.Factory;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

public class Calculator$$EnhancerByCGLIB$$345a285a extends Calculator 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$add$0$Method;
private static final MethodProxy CGLIB$add$0$Proxy;
private static final Object[] CGLIB$emptyArgs;
private static final Method CGLIB$sub$1$Method;
private static final MethodProxy CGLIB$sub$1$Proxy;
private static final Method CGLIB$mult$2$Method;
private static final MethodProxy CGLIB$mult$2$Proxy;
private static final Method CGLIB$div$3$Method;
private static final MethodProxy CGLIB$div$3$Proxy;
private static final Method CGLIB$equals$4$Method;
private static final MethodProxy CGLIB$equals$4$Proxy;
private static final Method CGLIB$toString$5$Method;
private static final MethodProxy CGLIB$toString$5$Proxy;
private static final Method CGLIB$hashCode$6$Method;
private static final MethodProxy CGLIB$hashCode$6$Proxy;
private static final Method CGLIB$clone$7$Method;
private static final MethodProxy CGLIB$clone$7$Proxy;

static void CGLIB$STATICHOOK1() {
CGLIB$THREAD_CALLBACKS = new ThreadLocal();
CGLIB$emptyArgs = new Object[0];
Class var0 = Class.forName("com.eitan.proxy.cglib.Calculator$$EnhancerByCGLIB$$345a285a");
Class var1;
Method[] var10000 = ReflectUtils.findMethods(new String[]{"add", "(II)I", "sub", "(II)I", "mult", "(II)I", "div", "(II)I"}, (var1 = Class.forName("com.eitan.proxy.cglib.Calculator")).getDeclaredMethods());
CGLIB$add$0$Method = var10000[0];
CGLIB$add$0$Proxy = MethodProxy.create(var1, var0, "(II)I", "add", "CGLIB$add$0");
CGLIB$sub$1$Method = var10000[1];
CGLIB$sub$1$Proxy = MethodProxy.create(var1, var0, "(II)I", "sub", "CGLIB$sub$1");
CGLIB$mult$2$Method = var10000[2];
CGLIB$mult$2$Proxy = MethodProxy.create(var1, var0, "(II)I", "mult", "CGLIB$mult$2");
CGLIB$div$3$Method = var10000[3];
CGLIB$div$3$Proxy = MethodProxy.create(var1, var0, "(II)I", "div", "CGLIB$div$3");
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$4$Method = var10000[0];
CGLIB$equals$4$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$4");
CGLIB$toString$5$Method = var10000[1];
CGLIB$toString$5$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/String;", "toString", "CGLIB$toString$5");
CGLIB$hashCode$6$Method = var10000[2];
CGLIB$hashCode$6$Proxy = MethodProxy.create(var1, var0, "()I", "hashCode", "CGLIB$hashCode$6");
CGLIB$clone$7$Method = var10000[3];
CGLIB$clone$7$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/Object;", "clone", "CGLIB$clone$7");
}

final int CGLIB$add$0(int var1, int var2) {
return super.add(var1, var2);
}

public final int add(int var1, int var2) {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}

if (var10000 != null) {
Object var3 = var10000.intercept(this, CGLIB$add$0$Method, new Object[]{new Integer(var1), new Integer(var2)}, CGLIB$add$0$Proxy);
return var3 == null ? 0 : ((Number)var3).intValue();
} else {
return super.add(var1, var2);
}
}

final int CGLIB$sub$1(int var1, int var2) {
return super.sub(var1, var2);
}

public final int sub(int var1, int var2) {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}

if (var10000 != null) {
Object var3 = var10000.intercept(this, CGLIB$sub$1$Method, new Object[]{new Integer(var1), new Integer(var2)}, CGLIB$sub$1$Proxy);
return var3 == null ? 0 : ((Number)var3).intValue();
} else {
return super.sub(var1, var2);
}
}

final int CGLIB$mult$2(int var1, int var2) {
return super.mult(var1, var2);
}

public final int mult(int var1, int var2) {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}

if (var10000 != null) {
Object var3 = var10000.intercept(this, CGLIB$mult$2$Method, new Object[]{new Integer(var1), new Integer(var2)}, CGLIB$mult$2$Proxy);
return var3 == null ? 0 : ((Number)var3).intValue();
} else {
return super.mult(var1, var2);
}
}

final int CGLIB$div$3(int var1, int var2) {
return super.div(var1, var2);
}

public final int div(int var1, int var2) {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}

if (var10000 != null) {
Object var3 = var10000.intercept(this, CGLIB$div$3$Method, new Object[]{new Integer(var1), new Integer(var2)}, CGLIB$div$3$Proxy);
return var3 == null ? 0 : ((Number)var3).intValue();
} else {
return super.div(var1, var2);
}
}

final boolean CGLIB$equals$4(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$4$Method, new Object[]{var1}, CGLIB$equals$4$Proxy);
return var2 == null ? false : (Boolean)var2;
} else {
return super.equals(var1);
}
}

final String CGLIB$toString$5() {
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$5$Method, CGLIB$emptyArgs, CGLIB$toString$5$Proxy) : super.toString();
}

final int CGLIB$hashCode$6() {
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$6$Method, CGLIB$emptyArgs, CGLIB$hashCode$6$Proxy);
return var1 == null ? 0 : ((Number)var1).intValue();
} else {
return super.hashCode();
}
}

final Object CGLIB$clone$7() 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$7$Method, CGLIB$emptyArgs, CGLIB$clone$7$Proxy) : super.clone();
}

public static MethodProxy CGLIB$findMethodProxy(Signature var0) {
String var10000 = var0.toString();
switch(var10000.hashCode()) {
case -2131682232:
if (var10000.equals("sub(II)I")) {
return CGLIB$sub$1$Proxy;
}
break;
case -1287932281:
if (var10000.equals("add(II)I")) {
return CGLIB$add$0$Proxy;
}
break;
case -1267343528:
if (var10000.equals("mult(II)I")) {
return CGLIB$mult$2$Proxy;
}
break;
case -508378822:
if (var10000.equals("clone()Ljava/lang/Object;")) {
return CGLIB$clone$7$Proxy;
}
break;
case 303407255:
if (var10000.equals("div(II)I")) {
return CGLIB$div$3$Proxy;
}
break;
case 1826985398:
if (var10000.equals("equals(Ljava/lang/Object;)Z")) {
return CGLIB$equals$4$Proxy;
}
break;
case 1913648695:
if (var10000.equals("toString()Ljava/lang/String;")) {
return CGLIB$toString$5$Proxy;
}
break;
case 1984935277:
if (var10000.equals("hashCode()I")) {
return CGLIB$hashCode$6$Proxy;
}
}

return null;
}

public Calculator$$EnhancerByCGLIB$$345a285a() {
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) {
Calculator$$EnhancerByCGLIB$$345a285a var1 = (Calculator$$EnhancerByCGLIB$$345a285a)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);
Calculator$$EnhancerByCGLIB$$345a285a var10000 = new Calculator$$EnhancerByCGLIB$$345a285a();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
}

public Object newInstance(Callback var1) {
CGLIB$SET_THREAD_CALLBACKS(new Callback[]{var1});
Calculator$$EnhancerByCGLIB$$345a285a var10000 = new Calculator$$EnhancerByCGLIB$$345a285a();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
}

public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) {
CGLIB$SET_THREAD_CALLBACKS(var3);
Calculator$$EnhancerByCGLIB$$345a285a var10000 = new Calculator$$EnhancerByCGLIB$$345a285a;
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();
}
}

add(int var1, int var2)

当主程序调用 add 方法后,实际调用的是被代理对象的 add 方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public final int add(int var1, int var2) {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}

if (var10000 != null) {
Object var3 = var10000.intercept(this, CGLIB$add$0$Method, new Object[]{new Integer(var1), new Integer(var2)}, CGLIB$add$0$Proxy);
return var3 == null ? 0 : ((Number)var3).intValue();
} else {
return super.add(var1, var2);
}
}

当首次进入时 this.CGLIB$CALLBACK_0 并未赋值,因此 var1000null,将会执行 CGLIB$BIND_CALLBACKS(this)

CGLIB$BIND_CALLBACKS(Object var0)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private static final void CGLIB$BIND_CALLBACKS(Object var0) {
Calculator$$EnhancerByCGLIB$$345a285a var1 = (Calculator$$EnhancerByCGLIB$$345a285a)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];
}

}

CGLIB$CALLBACK_0CGLIB$THREAD_CALLBACKS 调用 get() 方法后返回的 Callback[] 数组的第0个元素,而 CGLIB$THREAD_CALLBACKS 为一个静态的 ThreadLocal 对象且通过一个静态方法进行赋值。

1
2
3
public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] var0) {
CGLIB$THREAD_CALLBACKS.set(var0);
}

因此,我们只需要明白 CGLIB$SET_THREAD_CALLBACKS(Callback[] var0) 是何时被调用的,且传入的参数 Callback[] var0 为何值就能清楚代理对象在调用被代理方法的具体流程,而这个静态方法被调用的时机在 Calculator myCalculator = (Calculator) enhancer.create() 方法中。

浅析代理对象的创建方法 enhancer.create()

我们跳过各种对数据的包装和缓存的代码,可以看到真正对代理对象的创建代码在 Enhancer 的父类 AbstractClassGeneratorcreate(Object key) 方法中。

create()

1
2
3
4
5
public Object create() {
classOnly = false;
argumentTypes = null;
return createHelper();
}

createHelper()

1
2
3
4
5
6
7
8
9
10
11
12
13
private Object createHelper() {
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;
}

super.create(key)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
protected Object create(Object key) {
try {
ClassLoader loader = getClassLoader();
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;
// 这一步是生成代理对象的class文件的包装对象EnhancerFactoryData
Object obj = data.get(this, getUseCache());
if (obj instanceof Class) {
return firstInstance((Class) obj);
}
// 这一步通过代理对象的class文件将代理对象创建出来
return nextInstance(obj);
}
catch (RuntimeException | Error ex) {
throw ex;
}
catch (Exception ex) {
throw new CodeGenerationException(ex);
}
}

其中 Object obj = data.get(this, getUseCache()) 是生成代理对象的class文件的方法,而 nextInstance(obj) 方法则是通过代理对象的class文件将代理对象创建出来。代理对象的静态方法 CGLIB$SET_THREAD_CALLBACKS(Callback[] var0) 肯定是在其class文件生成之后被调用的,因此我们继续跟踪 nextInstance(obj) 方法。

Enhancer的nextInstance(Object instance)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
protected Object nextInstance(Object instance) {
EnhancerFactoryData data = (EnhancerFactoryData) instance;

if (classOnly) {
return data.generatedClass;
}

Class[] argumentTypes = this.argumentTypes;
Object[] arguments = this.arguments;
if (argumentTypes == null) {
argumentTypes = Constants.EMPTY_CLASS_ARRAY;
arguments = null;
}
return data.newInstance(argumentTypes, arguments, callbacks);
}

EnhancerFactoryData的newInstance(Class[] argumentTypes, Object[] arguments, Callback[] callbacks)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public Object newInstance(Class[] argumentTypes, Object[] arguments, Callback[] callbacks) {
// 调用代理的对象静态方法 CGLIB$SET_THREAD_CALLBACKS(Callback[] var0)
setThreadCallbacks(callbacks);
try {
// Explicit reference equality is added here just in case Arrays.equals does not have one
if (primaryConstructorArgTypes == argumentTypes ||
Arrays.equals(primaryConstructorArgTypes, argumentTypes)) {
// If we have relevant Constructor instance at hand, just call it
// This skips "get constructors" machinery
return ReflectUtils.newInstance(primaryConstructor, arguments);
}
// Take a slow path if observing unexpected argument types
return ReflectUtils.newInstance(generatedClass, argumentTypes, arguments);
}
finally {
// clear thread callbacks to allow them to be gc'd
setThreadCallbacks(null);
}

}

EnhancerFactoryDataEnhancer 的内部类,而这里的 setThreadCallbacks(callbacks) 的入参 callbacks 往上追溯来自于 Enhancer 类的属性private Callback[] callbacks,那这个属性是何时赋值的呢?将目光移向我们写道程序入口,我们将自定义的 MethodInterceptor 对象 MyCglib 创建并赋值给了 Enhancer 的对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
public class CglibTest {
public static void main(String[] args) {
// 设置cglib生成的class文件保存路径
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "E:\\mashibing\\spring");
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(Calculator.class);
// 对Enhancer类的callbacks属性赋值
enhancer.setCallback(new MyCglib());
Calculator myCalculator = (Calculator) enhancer.create();
myCalculator.add(1, 1);
System.out.println(myCalculator.getClass());
}
}

setThreadCallbacks(Callback[] callbacks)

1
2
3
4
5
6
7
8
9
10
11
private void setThreadCallbacks(Callback[] callbacks) {
try {
setThreadCallbacks.invoke(generatedClass, (Object) callbacks);
}
catch (IllegalAccessException e) {
throw new CodeGenerationException(e);
}
catch (InvocationTargetException e) {
throw new CodeGenerationException(e.getTargetException());
}
}

setThreadCallbacks 是代理类静态方法 CGLIB$SET_THREAD_CALLBACKS(Callback[] var0)Method 对象,generatedClass 为代理对象的 class 对象。这两个对象都是 EnhancerFactoryData 的内部属性字段,是通过 EnhancerFactoryData 的构造方法赋值的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public EnhancerFactoryData(Class generatedClass, Class[] primaryConstructorArgTypes, boolean classOnly) {
// 代理对象的class对象
this.generatedClass = generatedClass;
try {
// 通过class对象和方法名获取Method对象
setThreadCallbacks = getCallbacksSetter(generatedClass, SET_THREAD_CALLBACKS_NAME);
if (classOnly) {
this.primaryConstructorArgTypes = null;
this.primaryConstructor = null;
}
else {
this.primaryConstructorArgTypes = primaryConstructorArgTypes;
this.primaryConstructor = ReflectUtils.getConstructor(generatedClass, primaryConstructorArgTypes);
}
}
catch (NoSuchMethodException e) {
throw new CodeGenerationException(e);
}
}

MethodInterceptor的intercept方法是怎么实现代理的

通过以上讲解,我们得知代理对象 Calculator myCalculator = (Calculator) enhancer.create() 调用 myCalculator.add(1, 1) 方法,实际上会去调用我们在 Enhancer 对象中设置的回调对象 enhancer.setCallback(new MyCglib())intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) 方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public final int add(int var1, int var2) {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}

if (var10000 != null) {
Object var3 = var10000.intercept(this, CGLIB$add$0$Method, new Object[]{new Integer(var1), new Integer(var2)}, CGLIB$add$0$Proxy);
return var3 == null ? 0 : ((Number)var3).intValue();
} else {
return super.add(var1, var2);
}
}

我们先关注两个对象 CGLIB$add$0$MethodCGLIB$add$0$Proxy,这两个变量的赋值都在静态方法 CGLIB$STATICHOOK1() 中,这个方法在静态代码块中被调用,也就是说当代理类的class文件被加载到内存中时便已经执行了。

1
2
3
4
5
6
public class Calculator$$EnhancerByCGLIB$$345a285a extends Calculator implements Factory {    
...
static {
CGLIB$STATICHOOK1();
}
}

CGLIB$add$0$Method

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
static void CGLIB$STATICHOOK1() {
CGLIB$THREAD_CALLBACKS = new ThreadLocal();
CGLIB$emptyArgs = new Object[0];
Class var0 = Class.forName("com.eitan.proxy.cglib.Calculator$$EnhancerByCGLIB$$345a285a");
Class var1;
Method[] var10000 = ReflectUtils.findMethods(new String[]{"add", "(II)I", "sub", "(II)I", "mult", "(II)I", "div", "(II)I"}, (var1 = Class.forName("com.eitan.proxy.cglib.Calculator")).getDeclaredMethods());
CGLIB$add$0$Method = var10000[0];
CGLIB$add$0$Proxy = MethodProxy.create(var1, var0, "(II)I", "add", "CGLIB$add$0");
CGLIB$sub$1$Method = var10000[1];
CGLIB$sub$1$Proxy = MethodProxy.create(var1, var0, "(II)I", "sub", "CGLIB$sub$1");
CGLIB$mult$2$Method = var10000[2];
CGLIB$mult$2$Proxy = MethodProxy.create(var1, var0, "(II)I", "mult", "CGLIB$mult$2");
CGLIB$div$3$Method = var10000[3];
CGLIB$div$3$Proxy = MethodProxy.create(var1, var0, "(II)I", "div", "CGLIB$div$3");
...
}

可以看出,该成员变量是通过 var1 = Class.forName(“com.eitan.proxy.cglib.Calculator”)).getDeclaredMethods() 拿到被代理类的所有 Method 方法对象,然后按顺序依次赋值 CGLIB$add$0$Method = var10000[0] ,因此变量 CGLIB$add$0$Method 就代表被代理对象的 add方法的 Method 对象。

CGLIB$add$0$Proxy

这是 CGLIB 框架里的 MethodProxy 类的对象,通过 MethodProxy.create(var1, var0, “(II)I”, “add”, “CGLIB$add$0”) 方法构建。其中 var1 为被代理对象的class对象 var1 = Class.forName(“com.eitan.proxy.cglib.Calculator”)var0 为代理对象的class对象 Class var0 = Class.forName(“com.eitan.proxy.cglib.Calculator$$EnhancerByCGLIB$$345a285a”)

1
2
3
4
5
6
7
8
9
public static MethodProxy create(Class c1, Class c2, String desc, String name1, String name2) {
MethodProxy proxy = new MethodProxy();
// name1 = "add"
proxy.sig1 = new Signature(name1, desc);
// name2 = "CGLIB$add$0"
proxy.sig2 = new Signature(name2, desc);
proxy.createInfo = new CreateInfo(c1, c2);
return proxy;
}

其中 name1 = “add”name2 = “CGLIB$add$0” 是两个方法名:

  • add 方法:代理对象对原方法的增强,在其中调用了 MethodInterceptor 的 intercept 方法
  • CGLIB$add$0:直接调用父类的 add 方法,也就是直接调用被代理对象的 add 方法

methodProxy.invokeSuper(o, objects)

当我们知道了 MethodInterceptorintercept 方法的入参代表何值之后,我们将注意力放在自定义的 MethodInceptor 子类。

1
2
3
4
5
6
7
public class MyCglib implements MethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("调用cglib动态代理");
return methodProxy.invokeSuper(o, objects);
}
}

当代理对象执行 add(1, 1) 方法时,最终将调用该对象的 intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) 方法。从代理对象的class文件可以分析出这个方法的各个入参的实际含义:

  • Object o:代理对象
  • Method method:被代理类所执行方法的Method对象
  • Object[] objects:所执行方法的入参
  • MethodProxy methodProxy:cglib包下的类,包含了代理类和被代理类的class对象以及两个方法名 add 和 CGLIB$add$0

为什么methodProxy.invokeSuper(o, objects)方法会调用被代理对象的方法呢?

1
2
3
4
5
6
7
8
9
10
public Object invokeSuper(Object obj, Object[] args) throws Throwable {
try {
init();
FastClassInfo fci = fastClassInfo;
return fci.f2.invoke(fci.i2, obj, args);
}
catch (InvocationTargetException e) {
throw e.getTargetException();
}
}

init()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
private void init() {
/*
* Using a volatile invariant allows us to initialize the FastClass and
* method index pairs atomically.
*
* Double-checked locking is safe with volatile in Java 5. Before 1.5 this
* code could allow fastClassInfo to be instantiated more than once, which
* appears to be benign.
*/
if (fastClassInfo == null) {
synchronized (initLock) {
if (fastClassInfo == null) {
CreateInfo ci = createInfo;

FastClassInfo fci = new FastClassInfo();
// 生成被代理类的 FastClass 对象
fci.f1 = helper(ci, ci.c1);
// 生成代理类的 FastClass 对象
fci.f2 = helper(ci, ci.c2);
// 即调用被代理类的 FastClass 对象找出 sig1 包含的方法名 add 的下标
fci.i1 = fci.f1.getIndex(sig1);
// 即调用代理类的 FastClass 对象找出 sig2 包含的方法名 CGLIB$add$0 的下标
fci.i2 = fci.f2.getIndex(sig2);
fastClassInfo = fci;
createInfo = null;
}
}
}
}

fci.f2.invoke(fci.i2, obj, args);

调用代理类的 FastClass 对象的 invoke(fci.i2, obj, args) 方法,其中:

  • fci.i2:调用代理类的 FastClass 对象的 fci.f2.getIndex(sig2) 找出的索引
  • obj:methodProxy.invokeSuper(o, objects) 传入的对象 o,这里也就是代理对象
  • args:要调用的方法参数

Calculator$$EnhancerByCGLIB$$345a285a$$FastClassByCGLIB$$cfb242b8d代理对象的FastClass

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
public class Calculator$$EnhancerByCGLIB$$345a285a$$FastClassByCGLIB$$cfb242b8 extends FastClass {
public Calculator$$EnhancerByCGLIB$$345a285a$$FastClassByCGLIB$$cfb242b8(Class var1) {
super(var1);
}

public int getIndex(Signature var1) {
String var10000 = var1.toString();
switch(var10000.hashCode()) {
case -2131682232:
if (var10000.equals("sub(II)I")) {
return 8;
}
break;
case -1870561232:
if (var10000.equals("CGLIB$findMethodProxy(Lorg/springframework/cglib/core/Signature;)Lorg/springframework/cglib/proxy/MethodProxy;")) {
return 17;
}
break;
case -1860420502:
if (var10000.equals("CGLIB$clone$7()Ljava/lang/Object;")) {
return 22;
}
break;
case -1745842178:
if (var10000.equals("setCallbacks([Lorg/springframework/cglib/proxy/Callback;)V")) {
return 10;
}
break;
case -1641413109:
if (var10000.equals("newInstance([Lorg/springframework/cglib/proxy/Callback;)Ljava/lang/Object;")) {
return 5;
}
break;
case -1457535688:
if (var10000.equals("CGLIB$STATICHOOK1()V")) {
return 25;
}
break;
case -1411753352:
if (var10000.equals("CGLIB$hashCode$6()I")) {
return 20;
}
break;
case -1287932281:
if (var10000.equals("add(II)I")) {
return 0;
}
break;
case -1267343528:
if (var10000.equals("mult(II)I")) {
return 15;
}
break;
case -1034266769:
if (var10000.equals("CGLIB$SET_STATIC_CALLBACKS([Lorg/springframework/cglib/proxy/Callback;)V")) {
return 14;
}
break;
case -1025895669:
if (var10000.equals("CGLIB$SET_THREAD_CALLBACKS([Lorg/springframework/cglib/proxy/Callback;)V")) {
return 13;
}
break;
case -988317324:
if (var10000.equals("newInstance([Ljava/lang/Class;[Ljava/lang/Object;[Lorg/springframework/cglib/proxy/Callback;)Ljava/lang/Object;")) {
return 6;
}
break;
case -984241474:
if (var10000.equals("CGLIB$add$0(II)I")) {
return 26;
}
break;
case -974181657:
if (var10000.equals("CGLIB$mult$2(II)I")) {
return 23;
}
break;
case -629417301:
if (var10000.equals("CGLIB$div$3(II)I")) {
return 24;
}
break;
case -508378822:
if (var10000.equals("clone()Ljava/lang/Object;")) {
return 4;
}
break;
case -50496290:
if (var10000.equals("CGLIB$sub$1(II)I")) {
return 21;
}
break;
case 303407255:
if (var10000.equals("div(II)I")) {
return 16;
}
break;
case 593200387:
if (var10000.equals("CGLIB$equals$4(Ljava/lang/Object;)Z")) {
return 18;
}
break;
case 610042816:
if (var10000.equals("newInstance(Lorg/springframework/cglib/proxy/Callback;)Ljava/lang/Object;")) {
return 7;
}
break;
case 1132856532:
if (var10000.equals("getCallbacks()[Lorg/springframework/cglib/proxy/Callback;")) {
return 12;
}
break;
case 1246779367:
if (var10000.equals("setCallback(ILorg/springframework/cglib/proxy/Callback;)V")) {
return 9;
}
break;
case 1364367423:
if (var10000.equals("getCallback(I)Lorg/springframework/cglib/proxy/Callback;")) {
return 11;
}
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 1940521675:
if (var10000.equals("CGLIB$toString$5()Ljava/lang/String;")) {
return 19;
}
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 -1053468136:
if (var1.equals("getCallbacks")) {
switch(var2.length) {
case 0:
return 12;
}
}
break;
case -124978606:
if (var1.equals("CGLIB$equals$4")) {
switch(var2.length) {
case 1:
if (var2[0].getName().equals("java.lang.Object")) {
return 18;
}
}
}
break;
case -60403779:
if (var1.equals("CGLIB$SET_STATIC_CALLBACKS")) {
switch(var2.length) {
case 1:
if (var2[0].getName().equals("[Lorg.springframework.cglib.proxy.Callback;")) {
return 14;
}
}
}
break;
case -29025552:
if (var1.equals("CGLIB$hashCode$6")) {
switch(var2.length) {
case 0:
return 20;
}
}
break;
case 96417:
if (var1.equals("add")) {
switch(var2.length) {
case 2:
if (var2[0].getName().equals("int") && var2[1].getName().equals("int")) {
return 0;
}
}
}
break;
case 99473:
if (var1.equals("div")) {
switch(var2.length) {
case 2:
if (var2[0].getName().equals("int") && var2[1].getName().equals("int")) {
return 16;
}
}
}
break;
case 114240:
if (var1.equals("sub")) {
switch(var2.length) {
case 2:
if (var2[0].getName().equals("int") && var2[1].getName().equals("int")) {
return 8;
}
}
}
break;
case 3363120:
if (var1.equals("mult")) {
switch(var2.length) {
case 2:
if (var2[0].getName().equals("int") && var2[1].getName().equals("int")) {
return 15;
}
}
}
break;
case 85179481:
if (var1.equals("CGLIB$SET_THREAD_CALLBACKS")) {
switch(var2.length) {
case 1:
if (var2[0].getName().equals("[Lorg.springframework.cglib.proxy.Callback;")) {
return 13;
}
}
}
break;
case 94756189:
if (var1.equals("clone")) {
switch(var2.length) {
case 0:
return 4;
}
}
break;
case 147696667:
if (var1.equals("hashCode")) {
switch(var2.length) {
case 0:
return 3;
}
}
break;
case 161998109:
if (var1.equals("CGLIB$STATICHOOK1")) {
switch(var2.length) {
case 0:
return 25;
}
}
break;
case 357484609:
if (var1.equals("CGLIB$mult$2")) {
switch(var2.length) {
case 2:
if (var2[0].getName().equals("int") && var2[1].getName().equals("int")) {
return 23;
}
}
}
break;
case 495524492:
if (var1.equals("setCallbacks")) {
switch(var2.length) {
case 1:
if (var2[0].getName().equals("[Lorg.springframework.cglib.proxy.Callback;")) {
return 10;
}
}
}
break;
case 1108311562:
if (var1.equals("CGLIB$add$0")) {
switch(var2.length) {
case 2:
if (var2[0].getName().equals("int") && var2[1].getName().equals("int")) {
return 26;
}
}
}
break;
case 1111248381:
if (var1.equals("CGLIB$div$3")) {
switch(var2.length) {
case 2:
if (var2[0].getName().equals("int") && var2[1].getName().equals("int")) {
return 24;
}
}
}
break;
case 1125439466:
if (var1.equals("CGLIB$sub$1")) {
switch(var2.length) {
case 2:
if (var2[0].getName().equals("int") && var2[1].getName().equals("int")) {
return 21;
}
}
}
break;
case 1154623345:
if (var1.equals("CGLIB$findMethodProxy")) {
switch(var2.length) {
case 1:
if (var2[0].getName().equals("org.springframework.cglib.core.Signature")) {
return 17;
}
}
}
break;
case 1543336192:
if (var1.equals("CGLIB$toString$5")) {
switch(var2.length) {
case 0:
return 19;
}
}
break;
case 1811874389:
if (var1.equals("newInstance")) {
switch(var2.length) {
case 1:
String var10001 = var2[0].getName();
switch(var10001.hashCode()) {
case -1997738671:
if (var10001.equals("[Lorg.springframework.cglib.proxy.Callback;")) {
return 5;
}
break;
case 1364160985:
if (var10001.equals("org.springframework.cglib.proxy.Callback")) {
return 7;
}
}
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("[Lorg.springframework.cglib.proxy.Callback;")) {
return 6;
}
}
}
break;
case 1817099975:
if (var1.equals("setCallback")) {
switch(var2.length) {
case 2:
if (var2[0].getName().equals("int") && var2[1].getName().equals("org.springframework.cglib.proxy.Callback")) {
return 9;
}
}
}
break;
case 1905679803:
if (var1.equals("getCallback")) {
switch(var2.length) {
case 1:
if (var2[0].getName().equals("int")) {
return 11;
}
}
}
break;
case 1951977613:
if (var1.equals("CGLIB$clone$7")) {
switch(var2.length) {
case 0:
return 22;
}
}
}

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 {
345a285a var10000 = (345a285a)var2;
int var10001 = var1;

try {
switch(var10001) {
case 0:
return new Integer(var10000.add(((Number)var3[0]).intValue(), ((Number)var3[1]).intValue()));
case 1:
return new Boolean(var10000.equals(var3[0]));
case 2:
return var10000.toString();
case 3:
return new Integer(var10000.hashCode());
case 4:
return var10000.clone();
case 5:
return var10000.newInstance((Callback[])var3[0]);
case 6:
return var10000.newInstance((Class[])var3[0], (Object[])var3[1], (Callback[])var3[2]);
case 7:
return var10000.newInstance((Callback)var3[0]);
case 8:
return new Integer(var10000.sub(((Number)var3[0]).intValue(), ((Number)var3[1]).intValue()));
case 9:
var10000.setCallback(((Number)var3[0]).intValue(), (Callback)var3[1]);
return null;
case 10:
var10000.setCallbacks((Callback[])var3[0]);
return null;
case 11:
return var10000.getCallback(((Number)var3[0]).intValue());
case 12:
return var10000.getCallbacks();
case 13:
345a285a.CGLIB$SET_THREAD_CALLBACKS((Callback[])var3[0]);
return null;
case 14:
345a285a.CGLIB$SET_STATIC_CALLBACKS((Callback[])var3[0]);
return null;
case 15:
return new Integer(var10000.mult(((Number)var3[0]).intValue(), ((Number)var3[1]).intValue()));
case 16:
return new Integer(var10000.div(((Number)var3[0]).intValue(), ((Number)var3[1]).intValue()));
case 17:
return 345a285a.CGLIB$findMethodProxy((Signature)var3[0]);
case 18:
return new Boolean(var10000.CGLIB$equals$4(var3[0]));
case 19:
return var10000.CGLIB$toString$5();
case 20:
return new Integer(var10000.CGLIB$hashCode$6());
case 21:
return new Integer(var10000.CGLIB$sub$1(((Number)var3[0]).intValue(), ((Number)var3[1]).intValue()));
case 22:
return var10000.CGLIB$clone$7();
case 23:
return new Integer(var10000.CGLIB$mult$2(((Number)var3[0]).intValue(), ((Number)var3[1]).intValue()));
case 24:
return new Integer(var10000.CGLIB$div$3(((Number)var3[0]).intValue(), ((Number)var3[1]).intValue()));
case 25:
345a285a.CGLIB$STATICHOOK1();
return null;
case 26:
return new Integer(var10000.CGLIB$add$0(((Number)var3[0]).intValue(), ((Number)var3[1]).intValue()));
}
} catch (Throwable var4) {
throw new InvocationTargetException(var4);
}

throw new IllegalArgumentException("Cannot find matching method/constructor");
}

public Object newInstance(int var1, Object[] var2) throws InvocationTargetException {
345a285a var10000 = new 345a285a;
345a285a 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 26;
}
}

Calculator$$FastClassByCGLIB$$9bbbb4ed被代理对象的FastClass

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
public class Calculator$$FastClassByCGLIB$$9bbbb4ed extends FastClass {
public Calculator$$FastClassByCGLIB$$9bbbb4ed(Class var1) {
super(var1);
}

public int getIndex(Signature var1) {
String var10000 = var1.toString();
switch(var10000.hashCode()) {
case -2131682232:
if (var10000.equals("sub(II)I")) {
return 1;
}
break;
case -1287932281:
if (var10000.equals("add(II)I")) {
return 0;
}
break;
case -1267343528:
if (var10000.equals("mult(II)I")) {
return 2;
}
break;
case 303407255:
if (var10000.equals("div(II)I")) {
return 3;
}
break;
case 1826985398:
if (var10000.equals("equals(Ljava/lang/Object;)Z")) {
return 4;
}
break;
case 1913648695:
if (var10000.equals("toString()Ljava/lang/String;")) {
return 5;
}
break;
case 1984935277:
if (var10000.equals("hashCode()I")) {
return 6;
}
}

return -1;
}

public int getIndex(String var1, Class[] var2) {
switch(var1.hashCode()) {
case -1776922004:
if (var1.equals("toString")) {
switch(var2.length) {
case 0:
return 5;
}
}
break;
case -1295482945:
if (var1.equals("equals")) {
switch(var2.length) {
case 1:
if (var2[0].getName().equals("java.lang.Object")) {
return 4;
}
}
}
break;
case 96417:
if (var1.equals("add")) {
switch(var2.length) {
case 2:
if (var2[0].getName().equals("int") && var2[1].getName().equals("int")) {
return 0;
}
}
}
break;
case 99473:
if (var1.equals("div")) {
switch(var2.length) {
case 2:
if (var2[0].getName().equals("int") && var2[1].getName().equals("int")) {
return 3;
}
}
}
break;
case 114240:
if (var1.equals("sub")) {
switch(var2.length) {
case 2:
if (var2[0].getName().equals("int") && var2[1].getName().equals("int")) {
return 1;
}
}
}
break;
case 3363120:
if (var1.equals("mult")) {
switch(var2.length) {
case 2:
if (var2[0].getName().equals("int") && var2[1].getName().equals("int")) {
return 2;
}
}
}
break;
case 147696667:
if (var1.equals("hashCode")) {
switch(var2.length) {
case 0:
return 6;
}
}
}

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 {
Calculator var10000 = (Calculator)var2;
int var10001 = var1;

try {
switch(var10001) {
case 0:
return new Integer(var10000.add(((Number)var3[0]).intValue(), ((Number)var3[1]).intValue()));
case 1:
return new Integer(var10000.sub(((Number)var3[0]).intValue(), ((Number)var3[1]).intValue()));
case 2:
return new Integer(var10000.mult(((Number)var3[0]).intValue(), ((Number)var3[1]).intValue()));
case 3:
return new Integer(var10000.div(((Number)var3[0]).intValue(), ((Number)var3[1]).intValue()));
case 4:
return new Boolean(var10000.equals(var3[0]));
case 5:
return var10000.toString();
case 6:
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 {
Calculator var10000 = new Calculator;
Calculator 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 6;
}
}

所以,fci.f2.invoke(fci.i2, obj, args) 实际上会通过方法的索引 fci.i2 找出对应相应执行的方法,再通过传入的对象直接调用该方法达成目的。总结一句,FastClass 类将目标类的所有方法建立索引,且通过方法名可以找出对应下标,在代码里直接对传入对象进行方法调用,避免了使用反射造成的性能消耗。