背景
如 [Java] 从 class 文件看 cglib 对 InvocationHandler 的处理 一文所提到的, 使用 cglib 时,会用到 的子接口 ⬇️
它们的简要类图如下 ⬇️
本文关心的是 👇
下图单独展示了 和这两者的关系 👇
要点
Dispatcher 部分
LazyLoader 部分
代码
铺垫
下面举的例子有些牵强,因为我没有想出比较好的例子来 😂 大家凑合看吧。假设有一个 与门 的抽象类 ⬇️
public abstract class AbstractAndGate {
private void validateInputLength(boolean[] input) {
if (input.length == 0) {
throw new IllegalArgumentException("Input should have at least 1 element!");
}
}
public boolean calculate(boolean... input) {
validateInputLength(input);
for (boolean item : input) {
if (!item) {
return false;
}
}
return true;
}
}
AbstractAndGate 是抽象类,实际可用的 与门 是它的两个子类 ⬇️
CheapAndGateExpensiveAndGate
其中 CheapAndGate 的成本很低,即使在每次调用 calculate(boolean) 方法时,都创建新的 CheapAndGate 实例,也没问题。而 ExpensiveAndGate 的成本很高,我们希望最多只持有一个 ExpensiveAndGate 实例。
项目结构
我们在项目顶层执行 tree . 命令,会看到如下的结果 ⬇️
.
├── pom.xml
└── src
├── main
│ └── java
│ └── org
│ └── example
│ ├── AbstractAndGate.java
│ └── GateFactory.java
└── test
└── java
└── org
└── example
└── GateFactoryTest.java
10 directories, 4 files
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>cglib-study</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<!-- Source: https://mvnrepository.com/artifact/cglib/cglib -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.5.5</version> <!-- Use a recent version -->
<configuration>
<argLine>--add-opens=java.base/java.lang=ALL-UNNAMED</argLine>
</configuration>
</plugin>
</plugins>
</build>
</project>
AbstractAndGate.java
package org.example;
public abstract class AbstractAndGate {
private void validateInputLength(boolean[] input) {
if (input.length == 0) {
throw new IllegalArgumentException("Input should have at least 1 element!");
}
}
public boolean calculate(boolean... input) {
validateInputLength(input);
for (boolean item : input) {
if (!item) {
return false;
}
}
return true;
}
}
/**
* Assume that CheapAndGate is inexpensive,
* and it is OK to create a new instance for {@link AbstractAndGate#calculate(boolean...)} call.
*/
final class CheapAndGate extends AbstractAndGate {
public CheapAndGate() {
System.out.println("CheapAndGate instance is being created");
}
@Override
public String toString() {
return "CheapAndGate";
}
}
/**
* Assume that ExpensiveAndGate is expensive,
* and we need to cache it for {@link AbstractAndGate#calculate(boolean...)} calls.
*/
final class ExpensiveAndGate extends AbstractAndGate {
public ExpensiveAndGate() {
// Assume that there is some expensive work here
System.out.println("ExpensiveAndGate instance is being created");
}
@Override
public String toString() {
return "ExpensiveAndGate";
}
}
GateFactory.java
package org.example;
import net.sf.cglib.core.DebuggingClassWriter;
import net.sf.cglib.proxy.Dispatcher;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.LazyLoader;
public class GateFactory {
static {
// 将 cglib 生成的类保存到当前目录下
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, ".");
}
private static final Dispatcher dispatcher = CheapAndGate::new;
private static final LazyLoader lazyLoader = ExpensiveAndGate::new;
public static AbstractAndGate buildCheapAndGate() {
return (AbstractAndGate) Enhancer.create(AbstractAndGate.class, dispatcher);
}
public static AbstractAndGate buildExpensiveAndGate() {
return (AbstractAndGate) Enhancer.create(AbstractAndGate.class, lazyLoader);
}
}
GateFactoryTest.java
package org.example;
import net.sf.cglib.proxy.Dispatcher;
import net.sf.cglib.proxy.LazyLoader;
import org.junit.Assert;
import org.junit.Test;
import java.lang.reflect.Field;
public class GateFactoryTest {
@Test
public void testBuildCheapAndGate() {
AbstractAndGate cheapAndGate = GateFactory.buildCheapAndGate();
Assert.assertFalse(cheapAndGate.calculate(false, false));
Assert.assertFalse(cheapAndGate.calculate(false, true));
Assert.assertTrue(cheapAndGate.calculate(true, true));
}
@Test
public void testBuildExpensiveAndGate() {
AbstractAndGate expensiveAndGate = GateFactory.buildExpensiveAndGate();
Assert.assertFalse(expensiveAndGate.calculate(false, false));
Assert.assertFalse(expensiveAndGate.calculate(false, true));
Assert.assertTrue(expensiveAndGate.calculate(true, true));
}
@Test
public void testDispatcher() throws ReflectiveOperationException {
AbstractAndGate cheapAndGate = GateFactory.buildCheapAndGate();
Field dispatcherField = GateFactory.class.getDeclaredField("dispatcher");
dispatcherField.setAccessible(true);
Dispatcher dispatcher = (Dispatcher) dispatcherField.get(null);
Field cglibCallback0Field = cheapAndGate.getClass().getDeclaredField("CGLIB$CALLBACK_0");
cglibCallback0Field.setAccessible(true);
Dispatcher cglibCallback0 = (Dispatcher) cglibCallback0Field.get(cheapAndGate);
Assert.assertSame(cglibCallback0, dispatcher);
}
@Test
public void testLazyLoader() throws ReflectiveOperationException {
AbstractAndGate expensiveAndGate = GateFactory.buildExpensiveAndGate();
Field lazyLoaderField = GateFactory.class.getDeclaredField("lazyLoader");
lazyLoaderField.setAccessible(true);
LazyLoader lazyLoader = (LazyLoader) lazyLoaderField.get(null);
Field cglibLazyLoader0Field = expensiveAndGate.getClass().getDeclaredField("CGLIB$CALLBACK_0");
cglibLazyLoader0Field.setAccessible(true);
LazyLoader cglibLazyLoader0 = (LazyLoader) cglibLazyLoader0Field.get(expensiveAndGate);
Assert.assertSame(cglibLazyLoader0, lazyLoader);
}
}
AbstractAndGate/CheapAndGate/ExpensiveAndGate/GateFactoryT/GateFactoryTest 的类图如下 ⬇️
运行
在项目顶层执行如下命令,可以运行单元测试
mvn clean test
运行后,会看到项目顶层多了 net 和 org 这两个目录。执行 tree net org 命令后,会看到如下结果 ⬇️
net
└── sf
└── cglib
├── core
│ └── MethodWrapper$MethodWrapperKey$$KeyFactoryByCGLIB$$d45e49f7.class
└── proxy
└── Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$7fb24d72.class
org
└── example
├── AbstractAndGate$$EnhancerByCGLIB$$4542421f.class
└── AbstractAndGate$$EnhancerByCGLIB$$5ca9308f.class
7 directories, 4 files
以下两个文件看起来和 AbstractAndGate 直接相关
AbstractAndGate$$EnhancerByCGLIB$$4542421f.classAbstractAndGate$$EnhancerByCGLIB$$5ca9308f.class
我们在 Intellij IDEA (Community Edition) 可以看到这两个 class 文件反编译的结果(但完整的结果比较长,这里就不展示了)。下方是它们的类图 ⬇️
分析
我们先看 Dispatcher
Dispatcher
从 IntelliJ IDEA (Community Edition) 反编译的结果(如下图所示)来看,AbstractAndGate$$EnhancerByCGLIB$$5ca9308f 中的下列方法的处理逻辑类似 ⬇️
equals(Object)hashCode()toString()calculate(boolean...)
这些方法在调用 loadObject() 方法后,对它的返回值的处理有些差异(我在下图中用红线把有差异的地方标出来了)。
所以我们着重看一个方法就行了。我们来看看 calculate(boolean...) 方法 ⬇️
public final boolean calculate(boolean... var1) {
Dispatcher var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
return ((AbstractAndGate)var10000.loadObject()).calculate(var1);
}
看起来主线逻辑是这样的 ⬇️
那么以下两者是否为同一个引用呢?
AbstractAndGate$$EnhancerByCGLIB$$5ca9308f中的CGLIB$CALLBACK_0字段GateFactory中的dispatcher字段
我用如下的单元测试(上文已提供完整代码)验证了一下 ⬇️ 两者确实为同一个引用
那么,在代理类中使用 Dispatcher 的主线逻辑就可以这样概括了 ⬇️
我们再去看看 LazyLoader
LazyLoader
从 IntelliJ IDEA (Community Edition) 反编译的结果(如下图所示)来看,AbstractAndGate$$EnhancerByCGLIB$$4542421f 中的下列方法的处理逻辑类似 ⬇️
equals(Object)hashCode()toString()calculate(boolean...)
这些方法内部都调用了
CGLIB$LOAD_PRIVATE_0() 方法,后者的逻辑如下 ⬇️
private final synchronized Object CGLIB$LOAD_PRIVATE_0() {
Object var10000 = this.CGLIB$LAZY_LOADER_0;
if (var10000 == null) {
LazyLoader var10001 = this.CGLIB$CALLBACK_0;
if (var10001 == null) {
CGLIB$BIND_CALLBACKS(this);
var10001 = this.CGLIB$CALLBACK_0;
}
var10000 = this.CGLIB$LAZY_LOADER_0 = var10001.loadObject();
}
return var10000;
}
看起来 this.CGLIB$LAZY_LOADER_0 字段的赋值处理是懒式的。假设 this.CGLIB$CALLBACK_0 字段和 中 字段引用的是同一个对象。最初 this.CGLIB$LAZY_LOADER_0 为 null,下图第 43 行的 if 条件成立,第 50 行会给 this.CGLIB$LAZY_LOADER_0 赋值(所赋的值是 的一个实例)
那么之后再执行这个方法时,this.CGLIB$LAZY_LOADER_0 已经不是 null 了,下图第 43 行的 if 语句条件不成立,直接执行第 53 行。
但是假设毕竟是假设,还是要验证一下以下两者是否为同一个引用。
AbstractAndGate$$EnhancerByCGLIB$$4542421f中的CGLIB$CALLBACK_0字段GateFactory中的lazyLoader字段
我用如下的单元测试(上文已提供完整代码)验证了一下 ⬇️ 两者确实为同一个引用
那么,在代理类中使用 LazyLoader 的主线逻辑就可以这样概括了 ⬇️
其他
画 "net.sf.cglib.proxy.Callback 和它的子接口" 用到的代码
我用了 PlantUML 的插件来画那张图,所用到的代码如下 ⬇️
@startuml
title <i>net.sf.cglib.proxy.Callback</i> 和它的子接口
interface net.sf.cglib.proxy.Callback
interface net.sf.cglib.proxy.MethodInterceptor
interface net.sf.cglib.proxy.NoOp
interface net.sf.cglib.proxy.LazyLoader #lightgreen
interface net.sf.cglib.proxy.Dispatcher #lightgreen
interface net.sf.cglib.proxy.InvocationHandler
interface net.sf.cglib.proxy.FixedValue
net.sf.cglib.proxy.Callback <|-- net.sf.cglib.proxy.MethodInterceptor
net.sf.cglib.proxy.Callback <|-- net.sf.cglib.proxy.NoOp
net.sf.cglib.proxy.Callback <|-- net.sf.cglib.proxy.LazyLoader
net.sf.cglib.proxy.Callback <|-- net.sf.cglib.proxy.Dispatcher
net.sf.cglib.proxy.Callback <|-- net.sf.cglib.proxy.InvocationHandler
net.sf.cglib.proxy.Callback <|-- net.sf.cglib.proxy.FixedValue
note top of net.sf.cglib.proxy.Callback
这是一个 <i>marker interface</i>
(这个接口里没有定义任何方法)
end note
note as n1
它们是本文的主角
浅绿色背景表示强调
无特殊语义
end note
net.sf.cglib.proxy.LazyLoader .. n1
net.sf.cglib.proxy.Dispatcher .. n1
@enduml
画 "net.sf.cglib.proxy.LazyLoader 和 net.sf.cglib.proxy.Dispatcher" 用到的代码
我用了 PlantUML 的插件来画那张图,所用到的代码如下 ⬇️
@startuml
title <i>net.sf.cglib.proxy.LazyLoader</i> 和 <i>net.sf.cglib.proxy.Dispatcher</i>
interface net.sf.cglib.proxy.Callback
interface net.sf.cglib.proxy.LazyLoader
interface net.sf.cglib.proxy.Dispatcher
net.sf.cglib.proxy.Callback <|-- net.sf.cglib.proxy.LazyLoader
net.sf.cglib.proxy.Callback <|-- net.sf.cglib.proxy.Dispatcher
interface net.sf.cglib.proxy.Dispatcher {
Object loadObject() throws Exception
}
interface net.sf.cglib.proxy.LazyLoader {
Object loadObject() throws Exception
}
@enduml
画 "五个类的类图" 用到的代码
我用了 PlantUML 的插件来画那张图,所用到的代码如下 ⬇️
@startuml
'https://plantuml.com/class-diagram
title 五个类的类图
abstract class org.example.AbstractAndGate {
- void validateInputLength(boolean[])
+ boolean calculate(boolean...)
}
org.example.AbstractAndGate <|-- org.example.CheapAndGate
org.example.AbstractAndGate <|-- org.example.ExpensiveAndGate
class org.example.CheapAndGate {
+ CheapAndGate()
+ String toString()
}
class org.example.ExpensiveAndGate {
+ ExpensiveAndGate()
+ String toString()
}
class org.example.GateFactory {
- {static} Dispatcher dispatcher
- {static} LazyLoader lazyLoader
+ {static} AbstractAndGate buildCheapAndGate()
+ {static} AbstractAndGate buildExpensiveAndGate()
}
class org.example.GateFactoryTest {
+ void testBuildCheapAndGate()
+ void testBuildExpensiveAndGate()
+ void testDispatcher()
+ void testLazyLoader()
}
@enduml
画 "两个动态代理类的类图" 用到的代码
我用了 PlantUML 的插件来画那张图,所用到的代码如下 ⬇️
@startuml
'https://plantuml.com/class-diagram
title 两个动态代理类的类图
abstract class org.example.AbstractAndGate {
- void validateInputLength(boolean[])
+ boolean calculate(boolean...)
}
org.example.AbstractAndGate <|-- org.example.CheapAndGate
org.example.AbstractAndGate <|-- org.example.ExpensiveAndGate
class org.example.CheapAndGate {
+ CheapAndGate()
+ String toString()
}
class org.example.ExpensiveAndGate {
+ ExpensiveAndGate()
+ String toString()
}
interface net.sf.cglib.proxy.Factory {
Object newInstance(Callback callback)
Object newInstance(Callback[] callbacks)
Object newInstance(Class[] types, Object[] args, Callback[] callbacks)
Callback getCallback(int index)
void setCallback(int index, Callback callback)
void setCallbacks(Callback[] callbacks)
Callback[] getCallbacks()
}
net.sf.cglib.proxy.Factory <|.. org.example.AbstractAndGate$$EnhancerByCGLIB$$4542421f
org.example.AbstractAndGate <|-- org.example.AbstractAndGate$$EnhancerByCGLIB$$4542421f
class org.example.AbstractAndGate$$EnhancerByCGLIB$$4542421f {
- boolean CGLIB$BOUND
+ {static} Object CGLIB$FACTORY_DATA
- {static} final ThreadLocal CGLIB$THREAD_CALLBACKS
- {static} final Callback[] CGLIB$STATIC_CALLBACKS
- LazyLoader CGLIB$CALLBACK_0
- {static} Object CGLIB$CALLBACK_FILTER
- Object CGLIB$LAZY_LOADER_0
{static} void CGLIB$STATICHOOK2()
+ final boolean calculate(boolean...)
+ final boolean equals(Object)
+ final String toString()
+ final int hashCode()
- final synchronized Object CGLIB$LOAD_PRIVATE_0()
+ org.example.AbstractAndGate$$EnhancerByCGLIB$$4542421f()
+ {static} void CGLIB$SET_THREAD_CALLBACKS(Callback[])
+ {static} void CGLIB$SET_STATIC_CALLBACKS(Callback[])
- {static} final void CGLIB$BIND_CALLBACKS(Object)
+ Object newInstance(Callback[])
+ Object newInstance(Callback)
+ Object newInstance(Class[], Object[], Callback[])
+ Callback getCallback(int)
+ void setCallback(int, Callback)
+ Callback[] getCallbacks()
+ void setCallbacks(Callback[])
}
net.sf.cglib.proxy.Factory <|.. org.example.AbstractAndGate$$EnhancerByCGLIB$$5ca9308f
org.example.AbstractAndGate <|-- org.example.AbstractAndGate$$EnhancerByCGLIB$$5ca9308f
class org.example.AbstractAndGate$$EnhancerByCGLIB$$5ca9308f {
- boolean CGLIB$BOUND
+ {static} Object CGLIB$FACTORY_DATA
- {static} final ThreadLocal CGLIB$THREAD_CALLBACKS
- {static} final Callback[] CGLIB$STATIC_CALLBACKS
- net.sf.cglib.proxy.Dispatcher CGLIB$CALLBACK_0
- {static} Object CGLIB$CALLBACK_FILTER
{static} void CGLIB$STATICHOOK1()
+ final boolean calculate(boolean...)
+ final boolean equals(Object)
+ final String toString()
+ final int hashCode()
+ org.example.AbstractAndGate$$EnhancerByCGLIB$$5ca9308f()
+ {static} void CGLIB$SET_THREAD_CALLBACKS(Callback[])
+ {static} void CGLIB$SET_STATIC_CALLBACKS(Callback[])
- {static} final void CGLIB$BIND_CALLBACKS(Object)
+ Object newInstance(Callback[])
+ Object newInstance(Callback)
+ Object newInstance(Class[], Object[], Callback[])
+ Callback getCallback(int)
+ void setCallback(int, Callback)
+ Callback[] getCallbacks()
+ void setCallbacks(Callback[])
}
@enduml
画 "在代理类中使用 Dispatcher 的主线逻辑" 用到的代码
我用了 PlantUML 的插件来画那张图,所用到的代码如下 ⬇️
@startwbs
caption \n\n
' caption 的内容是为了防止掘金平台生成的水印遮盖图中的文字
* 在代理类中使用 <i>net.sf.cglib.proxy.Dispatcher</i> 的主线逻辑
**:将 <i>this.CGLIB$CALLBACK_0</i> 保存在局部变量 <b><i>var10000</i></b> 中
(两者的类型都是 <b><i>net.sf.cglib.proxy.Dispatcher</i></b>);
***_:可以简单认为以下两者引用的是同一个对象
<&star> <i>this.CGLIB$CALLBACK_0</i>
<&star> <i>org.example.GateFactory</i> 中的 <b><i>dispatcher</i></b> 字段;
**:调用 <b><i>var10000.loadObject()</i><b> 方法,
并将返回值转化为 <i>AbstractAndGate</i> 类型
(我们将转化后的值简称为 <b><i>aag</i><b>);
***_:每次调用 <b><i>var10000.loadObject()</i><b> 方法时,
都会生成一个新的
<i>org.example.CheapAndGate</i> 实例;
**:执行 <i><b>aag</b>.calculate(var1)</i>,
并将它的返回值作为当前方法的返回值;
@endwbs
画 "在代理类中使用 net.sf.cglib.proxy.LazyLoader 的主线逻辑" 用到的代码
我用了 PlantUML 的插件来画那张图,所用到的代码如下 ⬇️
@startwbs
caption \n\n
' caption 的内容是为了防止掘金平台生成的水印遮盖图中的文字
* 在代理类中使用 <i>net.sf.cglib.proxy.LazyLoader</i> 的主线逻辑
**:调用 <b><i>CGLIB$LOAD_PRIVATE_0()</i></b> 方法,
获取 <b><i>org.example.ExpensiveAndGate</i></b> 的实例 <b><i>eag</i></b>;
***:如果 <b><i>this.CGLIB$LAZY_LOADER_0</i></b> 是 <i>null</i>
则执行 <b><i>this.CGLIB$CALLBACK_0.loadObject()</i></b>
(会得到一个 <b><i>org.example.ExpensiveAndGate</i></b> 实例),
并将结果赋值给 <b><i>this.CGLIB$LAZY_LOADER_0</i></b>;
*** 返回 <b><i>this.CGLIB$LAZY_LOADER_0</i></b>
**:执行 <i><b>eag</b>.calculate(var1)</i>
并将它的返回值作为当前方法的返回值;
@endwbs
画 "要点(Dispatcher 部分)" 用到的代码
我用了 PlantUML 的插件来画那张图,所用到的代码如下 ⬇️
@startuml
title 要点(<i>Dispatcher</i> 部分)
caption \n\n
' caption 中的内容只是为了防止掘金平台的水印遮盖图中的文字
interface Callback
interface Dispatcher
Callback <|-- Dispatcher
interface Dispatcher {
Object loadObject() throws Exception
}
class SomeClass {
+ void someMethod()
}
class SomeDispatcher {
+ Object loadObject() throws Exception
}
Dispatcher <|.. SomeDispatcher
class "Proxy<sub>SomeClass</sub>" as P
class P {
- Dispatcher CGLIB$CALLBACK_0
+ final void someMethod()
}
SomeClass <|-- P
note as n1
通过如下代码可以生成 SomeClass 的动态代理类: Proxy<sub>SomeClass</sub>
<code>
(SomeClass) Enhancer.create(SomeClass.class, new SomeDispatcher());
</code>
end note
SomeClass <.. n1: 用户指定的类 SomeClass
n1 ..> P: 生成的动态代理类 Proxy<sub>SomeClass</sub>
note right of SomeDispatcher
用户提供的 <i>Dispatcher</i> 的实现类
end note
P::CGLIB$CALLBACK_0 ..> SomeDispatcher : 该字段持有一个 SomeDispatcher 的实例
header
这张图里是以 <b>类</b> 为例, 描述了相关的要点
如果用户指定的是某个 <b>接口</b> <i>SomeInterface</i>, 那么 <i>cglib</i> 也可以用类似的方式进行处理
end header
note left of P::someMethod
可以认为它的代码是这样的 <:point_down:> (可以先忽略其中的 if 语句块)
<code>
public final void someMethod() {
Dispatcher var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
((SomeClass)var10000.loadObject()).someMethod();
}
</code>
end note
@enduml
画 "要点(LazyLoader 部分)" 用到的代码
我用了 PlantUML 的插件来画那张图,所用到的代码如下 ⬇️
@startuml
title 要点(<i>LazyLoader</i> 部分)
caption \n\n
' caption 中的内容只是为了防止掘金平台的水印遮盖图中的文字
interface Callback
interface LazyLoader
Callback <|-- LazyLoader
interface LazyLoader {
Object loadObject() throws Exception
}
class SomeClass {
+ void someMethod()
}
class SomeLazyLoader {
+ Object loadObject() throws Exception
}
LazyLoader <|.. SomeLazyLoader
class "Proxy<sub>SomeClass</sub>" as P
class P {
- LazyLoader CGLIB$CALLBACK_0
- Object CGLIB$LAZY_LOADER_0
+ final void someMethod()
- final synchronized Object CGLIB$LOAD_PRIVATE_0()
}
SomeClass <|-- P
note as n1
通过如下代码可以生成 SomeClass 的动态代理类: Proxy<sub>SomeClass</sub>
<code>
(SomeClass) Enhancer.create(SomeClass.class, new SomeLazyLoader());
</code>
end note
SomeClass <.. n1: 用户指定的类 SomeClass
n1 ..> P: 生成的动态代理类 Proxy<sub>SomeClass</sub>
note right of SomeLazyLoader
用户提供的 <i>LazyLoader</i> 的实现类
end note
P::CGLIB$CALLBACK_0 ..> SomeLazyLoader : 该字段持有一个 SomeLazyLoader 的实例
header
这张图里是以 <b>类</b> 为例, 描述了相关的要点
如果用户指定的是某个 <b>接口</b> <i>SomeInterface</i>, 那么 <i>cglib</i> 也可以用类似的方式进行处理
end header
note left of P::CGLIB$LAZY_LOADER_0
这个字段用 lazy 的方式,
保存 <i>SomeLazyLoader.loadObject()</i> 的返回值
end note
note left of P::someMethod
可以认为它的代码是这样的 <:point_down:>
<code>
public final void someMethod() {
((SomeClass)this.CGLIB$LOAD_PRIVATE_0()).someMethod();
}
</code>
end note
note left of P::CGLIB$LOAD_PRIVATE_0
可以认为它的代码是这样的 <:point_down:>
<code>
private final synchronized Object CGLIB$LOAD_PRIVATE_0() {
Object var10000 = this.CGLIB$LAZY_LOADER_0;
if (var10000 == null) {
LazyLoader var10001 = this.CGLIB$CALLBACK_0;
... // 为了简化主线逻辑, 我在这个地方省略了一个 if 语句块
var10000 = this.CGLIB$LAZY_LOADER_0 = var10001.loadObject();
}
return var10000;
}
</code>
end note
@enduml