背景
在 [Java] 从 class 文件看 cglib 对 MethodInterceptor 的处理 (上) 一文中,我们已经初步探讨了下方的问题,本文会继续探讨这个问题。
- 为什么 <math xmlns="http://www.w3.org/1998/Math/MathML"> net.sf.cglib.proxy.MethodInterceptor \text{net.sf.cglib.proxy.MethodInterceptor} </math>net.sf.cglib.proxy.MethodInterceptor 可以调用动态代理类的基类(即例子中的 <math xmlns="http://www.w3.org/1998/Math/MathML"> org.example.Adder \text{org.example.Adder} </math>org.example.Adder 类)中的方法
- <math xmlns="http://www.w3.org/1998/Math/MathML"> net.sf.cglib.reflect.FastClass \text{net.sf.cglib.reflect.FastClass} </math>net.sf.cglib.reflect.FastClass 会为 <math xmlns="http://www.w3.org/1998/Math/MathML"> org.example.Adder \text{org.example.Adder} </math>org.example.Adder 中定义的非私有方法分配编号(
index) - 通过使用这个编号(
index),我们可以调用 <math xmlns="http://www.w3.org/1998/Math/MathML"> org.example.Adder \text{org.example.Adder} </math>org.example.Adder 中对应的方法
- <math xmlns="http://www.w3.org/1998/Math/MathML"> net.sf.cglib.reflect.FastClass \text{net.sf.cglib.reflect.FastClass} </math>net.sf.cglib.reflect.FastClass 会为 <math xmlns="http://www.w3.org/1998/Math/MathML"> org.example.Adder \text{org.example.Adder} </math>org.example.Adder 中定义的非私有方法分配编号(
要点
- <math xmlns="http://www.w3.org/1998/Math/MathML"> Adder \text{Adder} </math>Adder 类中定义了 <math xmlns="http://www.w3.org/1998/Math/MathML"> a d d ( i n t , i n t ) add(int, int) </math>add(int,int) 方法
- <math xmlns="http://www.w3.org/1998/Math/MathML"> cglib \text{cglib} </math>cglib 为 <math xmlns="http://www.w3.org/1998/Math/MathML"> Adder \text{Adder} </math>Adder 类生成的子类(简称为 <math xmlns="http://www.w3.org/1998/Math/MathML"> Adder enhancer \text{Adder}_\text{enhancer} </math>Adderenhancer)中会有以下两个方法
- <math xmlns="http://www.w3.org/1998/Math/MathML"> CGLIBadd0(int, int) \text{CGLIB{\textdollar}add{\textdollar}0(int, int)} </math>CGLIBadd0(int, int): 它的逻辑是调用 基类 中的 <math xmlns="http://www.w3.org/1998/Math/MathML"> add(int, int) \text{add(int, int)} </math>add(int, int) 方法并返回对应的值
- <math xmlns="http://www.w3.org/1998/Math/MathML"> add(int, int) \text{add(int, int)} </math>add(int, int)
- <math xmlns="http://www.w3.org/1998/Math/MathML"> Adder \text{Adder} </math>Adder 类的子类 <math xmlns="http://www.w3.org/1998/Math/MathML"> Adder e n h a n c e r \text{Adder}_{enhancer} </math>Adderenhancer 中有 <math xmlns="http://www.w3.org/1998/Math/MathML"> MethodProxy \text{MethodProxy} </math>MethodProxy 类型的 <math xmlns="http://www.w3.org/1998/Math/MathML"> CGLIBadd0Proxy \\text{CGLIB\\textdollar add\\textdollar 0\\textdollar Proxy} CGLIBadd0Proxy 字段
- 对 <math xmlns="http://www.w3.org/1998/Math/MathML"> CGLIBadd0Proxy \\text{CGLIB\\textdollar add\\textdollar 0\\textdollar Proxy} CGLIBadd0Proxy 的 <math xmlns="http://www.w3.org/1998/Math/MathML"> invokeSuper(Object obj, Object[] args) \text{invokeSuper(Object obj, Object[] args)} </math>invokeSuper(Object obj, Object[] args) 方法的调用,最终会转化为 <math xmlns="http://www.w3.org/1998/Math/MathML"> ( ( Adder enhancer ) o b j ) . CGLIBadd0 ( ( ( Number ) args[0] ) . intValue() , ( ( Number ) args[1] ) . intValue() ) ((\text{Adder}_\text{enhancer}) obj).\text{CGLIB{\textdollar}add{\textdollar}0}(((\text{Number})\text{args[0]}).\text{intValue()}, ((\text{Number})\text{args[1]}).\text{intValue()}) </math>((Adderenhancer)obj).CGLIBadd0(((Number)args[0]).intValue(),((Number)args[1]).intValue()) 这样的逻辑
- 对 <math xmlns="http://www.w3.org/1998/Math/MathML"> CGLIBadd0Proxy \\text{CGLIB\\textdollar add\\textdollar 0\\textdollar Proxy} CGLIBadd0Proxy 的
invoke(Object obj, Object[] args)方法的调用,最终会转化为((Adder) obj).add(((Number)args[0]).intValue(), ((Number)args[1]).intValue())这样的逻辑
正文
项目结构
项目结构和 [Java] 从 class 文件看 cglib 对 MethodInterceptor 的处理 (上) 一文相同,可以参考那篇文章里的 项目结构 这一小节。
分析
两个 <math xmlns="http://www.w3.org/1998/Math/MathML"> net.sf.cglib.reflect.FastClass \text{net.sf.cglib.reflect.FastClass} </math>net.sf.cglib.reflect.FastClass
在 [Java] 如何通过 cglib 的 FastClass 调用一个类中的"任意"方法? 一文中,我们已经了解到,对一个类 <math xmlns="http://www.w3.org/1998/Math/MathML"> C \text{C} </math>C 而言,借助对应的 <math xmlns="http://www.w3.org/1998/Math/MathML"> net.sf.cglib.reflect.FastClass : FastClass C \text{net.sf.cglib.reflect.FastClass}: \text{FastClass}_\text{C} </math>net.sf.cglib.reflect.FastClass:FastClassC,我们可以(不通过反射 )调用 <math xmlns="http://www.w3.org/1998/Math/MathML"> C \text{C} </math>C 中定义的任意非私有方法。
那么如果我们既有和 <math xmlns="http://www.w3.org/1998/Math/MathML"> org.example.Adder \text{org.example.Adder} </math>org.example.Adder 对应的 <math xmlns="http://www.w3.org/1998/Math/MathML"> net.sf.cglib.reflect.FastClass \text{net.sf.cglib.reflect.FastClass} </math>net.sf.cglib.reflect.FastClass(可以简称为 <math xmlns="http://www.w3.org/1998/Math/MathML"> FastClass 1 \text{FastClass}_1 </math>FastClass1),又有和 <math xmlns="http://www.w3.org/1998/Math/MathML"> org.example.Adder \text{org.example.Adder} </math>org.example.Adder 的子类对应的 <math xmlns="http://www.w3.org/1998/Math/MathML"> net.sf.cglib.reflect.FastClass \text{net.sf.cglib.reflect.FastClass} </math>net.sf.cglib.reflect.FastClass(可以简称为 <math xmlns="http://www.w3.org/1998/Math/MathML"> FastClass 2 \text{FastClass}_2 </math>FastClass2),那么就可以自由调用我们在 <math xmlns="http://www.w3.org/1998/Math/MathML"> org.example.Adder \text{org.example.Adder} </math>org.example.Adder 中定义的方法了 ⬇️

| 类名 | 对应的 FastClass 是什么 |
|---|---|
Adder |
Adder$$FastClassByCGLIB$$2ea8c1e0 |
Adder$$EnhancerByCGLIB$$82ff904 (Adder 的子类) |
Adder$$EnhancerByCGLIB$$82ff904$$FastClassByCGLIB$$8d93dfdd |
这两个 <math xmlns="http://www.w3.org/1998/Math/MathML"> net.sf.cglib.reflect.FastClass \text{net.sf.cglib.reflect.FastClass} </math>net.sf.cglib.reflect.FastClass 子类的名称太长了,为了便于描述,我们把它们分别简称为 ⬇️
- <math xmlns="http://www.w3.org/1998/Math/MathML"> FastClass 1 \text{FastClass}_1 </math>FastClass1 (和 <math xmlns="http://www.w3.org/1998/Math/MathML"> org.example.Adder \text{org.example.Adder} </math>org.example.Adder 对应)
- <math xmlns="http://www.w3.org/1998/Math/MathML"> FastClass 2 \text{FastClass}_2 </math>FastClass2 (和 <math xmlns="http://www.w3.org/1998/Math/MathML"> org.example.Adder \text{org.example.Adder} </math>org.example.Adder 的子类对应)
我们分别看看对应的代码是什么样子的
Adder 对应的 FastClass: <math xmlns="http://www.w3.org/1998/Math/MathML"> FastClass 1 \text{FastClass}_1 </math>FastClass1
<math xmlns="http://www.w3.org/1998/Math/MathML"> org.example.Adder \text{org.example.Adder} </math>org.example.Adder 对应的 <math xmlns="http://www.w3.org/1998/Math/MathML"> net.sf.cglib.reflect.FastClass \text{net.sf.cglib.reflect.FastClass} </math>net.sf.cglib.reflect.FastClass 是 Adder$$FastClassByCGLIB$$2ea8c1e0 (简称为 <math xmlns="http://www.w3.org/1998/Math/MathML"> FastClass 1 \text{FastClass}_1 </math>FastClass1),借助 IntelliJ IDEA (Community Edition) 可以看到 Adder$$FastClassByCGLIB$$2ea8c1e0.class 反编译的结果。完整的结果比较长,与本文相关的内容如下(不相关的内容用 ... 表示)
java
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package org.example;
...
public class Adder$$FastClassByCGLIB$$2ea8c1e0 extends FastClass {
...
public int getIndex(String var1, Class[] var2) {
switch (var1.hashCode()) {
...
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;
...
}
...
public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {
Adder var10000 = (Adder)var2;
int var10001 = var1;
try {
switch (var10001) {
case 0:
return new Integer(var10000.add(((Number)var3[0]).intValue(), ((Number)var3[1]).intValue()));
...
}
}
...
}
...
}
Adder 的子类对应的 FastClass: <math xmlns="http://www.w3.org/1998/Math/MathML"> FastClass 2 \text{FastClass}_2 </math>FastClass2
Adder$$EnhancerByCGLIB$$82ff904 是 Adder 的子类,前者对应的 <math xmlns="http://www.w3.org/1998/Math/MathML"> net.sf.cglib.reflect.FastClass \text{net.sf.cglib.reflect.FastClass} </math>net.sf.cglib.reflect.FastClass 是 Adder$$EnhancerByCGLIB$$82ff904$$FastClassByCGLIB$$8d93dfdd(简称为 <math xmlns="http://www.w3.org/1998/Math/MathML"> FastClass 2 \text{FastClass}_2 </math>FastClass2),借助 IntelliJ IDEA (Community Edition) 可以看到 Adder$$EnhancerByCGLIB$$82ff904$$FastClassByCGLIB$$8d93dfdd.class 反编译的结果。完整的结果比较长,与本文相关的内容如下(不相关的内容用 ... 表示)
(在您的电脑上,Adder$$EnhancerByCGLIB$$82ff904$$FastClassByCGLIB$$8d93dfdd.class 的内容可能会有差异)
java
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package org.example;
...
public class Adder$$EnhancerByCGLIB$$82ff904$$FastClassByCGLIB$$8d93dfdd extends FastClass {
...
public int getIndex(String var1, Class[] var2) {
switch (var1.hashCode()) {
...
case 96417:
if (var1.equals("add")) {
switch (var2.length) {
case 2:
if (var2[0].getName().equals("int") && var2[1].getName().equals("int")) {
return 4;
}
}
}
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 17;
}
}
}
break;
...
}
...
public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {
// 由于反编译的结果对 '$' 的处理有点 bug,我手动调整了下一行的内容
Adder$$EnhancerByCGLIB$$82ff904 var10000 = (Adder$$EnhancerByCGLIB$$82ff904)var2;
int var10001 = var1;
try {
switch (var10001) {
...
case 4:
return new Integer(var10000.add(((Number)var3[0]).intValue(), ((Number)var3[1]).intValue()));
...
case 17:
return new Integer(var10000.CGLIB$add$0(((Number)var3[0]).intValue(), ((Number)var3[1]).intValue()));
...
}
}
...
}
...
}
AdderFactory 中的 methodInterceptor
AdderFactory 中的 methodInterceptor 字段对应的代码如下
java
private static final MethodInterceptor methodInterceptor =
(obj, method, args, proxy) -> {
if (method.getName().equals("add")) {
String message = String.format("The arguments for the add method are: %s",
Arrays.toString(args));
System.out.println(message);
}
return proxy.invokeSuper(obj, args);
};
当我们运行 AdderFactoryTest 中的 testBuildAdder 方法时,adder 会是 Adder$$EnhancerByCGLIB$$82ff904 的实例 ⬇️

Adder$$EnhancerByCGLIB$$82ff904 的 add(int, int) 方法反编译的结果如下
java
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$Proxy 是 <math xmlns="http://www.w3.org/1998/Math/MathML"> net.sf.cglib.proxy.MethodProxy \text{net.sf.cglib.proxy.MethodProxy} </math>net.sf.cglib.proxy.MethodProxy 的实例

其他
画 "对 FastClass 的使用" 一图所用到的代码
puml
@startuml
'https://plantuml.com/class-diagram
title 对 <i>FastClass</i> 的使用
caption 图中只画了本文关心的内容\n<i>FastClass</i> 和它的子类, 在图中用 <b>粉色</b> 标出来了
class org.example.Adder
class org.example.Adder$$EnhancerByCGLIB$$82ff904
org.example.Adder <|-- org.example.Adder$$EnhancerByCGLIB$$82ff904
class org.example.Adder {
+ int add(int a, int b)
}
class org.example.Adder$$EnhancerByCGLIB$$82ff904 {
- MethodInterceptor CGLIB$CALLBACK_0
- {static} final MethodProxy CGLIB$add$0$Proxy
+ final int add(int, int)
final int CGLIB$add$0(int, int)
}
abstract class net.sf.cglib.reflect.FastClass #pink {
+ {abstract} int getIndex(String name, Class[] parameterTypes)
+ {abstract} Object invoke(int index, Object obj, Object[] args) throws InvocationTargetException
}
class org.example.Adder$$FastClassByCGLIB$$2ea8c1e0
net.sf.cglib.reflect.FastClass <|-- org.example.Adder$$FastClassByCGLIB$$2ea8c1e0
class org.example.Adder$$FastClassByCGLIB$$2ea8c1e0 #pink {
+ int getIndex(String, Class[])
+ Object invoke(int, Object, Object[]) throws InvocationTargetException
}
note top of org.example.Adder$$FastClassByCGLIB$$2ea8c1e0
它为 <i>org.example.Adder</i> 中的
一些方法分配了编号 (<i>index</i>) <:point_down:>
| <b>方法</b> | <b>对应的 <i>index</i></b> |
| <b><i>add(int, int)</i></b> | <b><i>0</i></b> |
|...|...|
end note
class org.example.Adder$$EnhancerByCGLIB$$82ff904$$FastClassByCGLIB$$8d93dfdd
net.sf.cglib.reflect.FastClass <|-- org.example.Adder$$EnhancerByCGLIB$$82ff904$$FastClassByCGLIB$$8d93dfdd
class org.example.Adder$$EnhancerByCGLIB$$82ff904$$FastClassByCGLIB$$8d93dfdd #pink {
+ int getIndex(String, Class[])
+ Object invoke(int, Object, Object[]) throws InvocationTargetException
}
note top of org.example.Adder$$EnhancerByCGLIB$$82ff904$$FastClassByCGLIB$$8d93dfdd
它为 <i>org.example.Adder</i> 的 <b>子类</b> 中的
一些方法分配了编号 (<i>index</i>) <:point_down:>
(在您的电脑上, 对应的 <i>index</i> 也许会有差异)
| <b>方法</b> | <b>对应的 <i>index</i></b> |
|...|...|
| <b><i>add(int, int)</i></b> | <b><i>4</i></b> |
|...|...|
| <b><i>CGLIB$add$0(int, int)</i></b> | <b><i>17</i></b> |
|...|...|
end note
org.example.Adder <.. org.example.Adder$$FastClassByCGLIB$$2ea8c1e0 : 和 <b><i>org.example.Adder</i></b> 对应
org.example.Adder$$EnhancerByCGLIB$$82ff904 <.. org.example.Adder$$EnhancerByCGLIB$$82ff904$$FastClassByCGLIB$$8d93dfdd : 和 <b><i>org.example.Adder$$EnhancerByCGLIB$$82ff904</i></b> 对应
@enduml
画 "MethodProxy 中的 FastClassInfo" 一图所用到的代码
puml
@startuml
title <i>MethodProxy</i> 中的 <i>FastClassInfo</i>
caption 图中只画了本文关心的内容
class net.sf.cglib.proxy.MethodProxy {
- volatile FastClassInfo fastClassInfo
}
class net.sf.cglib.proxy.MethodProxy$FastClassInfo {
FastClass f1
FastClass f2
int i1
int i2
}
object o {
f1: <i>FastClass<sub>1</sub></i> 的实例
f2: <i>FastClass<sub>2</sub></i> 的实例
i1: 0 (和 <i>Adder</i> 类中的 <b><i>add(int, int)</i></b> 方法对应的 <b><i>index</i></b> 的值)
i2: 17 (和 <i>Adder</i> 类子类中的 <b><i>CGLIB$add$0(int, int)</i></b> 方法对应的 <b><i>index</i></b> 的值)
}
o ..> net.sf.cglib.proxy.MethodProxy$FastClassInfo: <i>o</i> 是 <i>net.sf.cglib.proxy.MethodProxy$FastClassInfo</i> 的实例
note as n1
<i>o</i> 和 <b><i>Adder$$EnhancerByCGLIB$$82ff904</i></b> 类的
<b><i>CGLIB$add$0$Proxy</i></b> 字段持有相同的引用
end note
o .. n1
@enduml