cglib动态代理的实现原理
1、示例代码
package com.zcqby.proxy.cglib;
public class MyCalculator {
public int add(int i, int j) {
int result = i + j;
return result;
}
public int sub(int i, int j) {
int result = i - j;
return result;
}
public int mult(int i, int j) {
int result = i * j;
return result;
}
public int div(int i, int j) {
int result = i / j;
return result;
}
}
package com.zcqby.proxy.cglib;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class MyCglib implements MethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
Object o1 = methodProxy.invokeSuper(o, objects);
return o1;
}
}
package com.zcqby.proxy.cglib;
import org.springframework.cglib.core.DebuggingClassWriter;
import org.springframework.cglib.proxy.Enhancer;
public class MyTest {
public static void main(String[] args) {
//动态代理创建的class文件存储到本地
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY,"d:\\code");
//通过cglib动态代理获取代理对象的过程,创建调用的对象,在后续创建过程中EnhanceKey的对象,所以在进行enhancer对象创建的时候需要把EnhancerKey(newInstance)对象准备好,恰好这个对象也需要动态代理来生成
Enhancer enhancer = new Enhancer();
//设置enhancer对象的父类
enhancer.setSuperclass(MyCalculator.class);
//设置enhancer的回调对象
enhancer.setCallback(new MyCglib());
//创建代理对象
MyCalculator myCalculator = (MyCalculator) enhancer.create();
//通过代理对象调用目标方法
myCalculator.add(1,1);
System.out.println(myCalculator.getClass());
}
}
2、源码跟踪
2.1、注意事项:
- 调试的时候, 如果想更详细的了解原理, 需要将断点打在
Enhancer enhancer = new Enhancer();
这里, 原因是 这边就已经创建了 缓存对象 ClassLoaderData
。
- 在常见过程中,我们要了解一个抽象类
FastClass
, CGLib
在运行时通过 FastClass
内 的Generator
这个内部类将其子类动态生成出来 ,然后再利用 ClassLoader
将 生成子类加载进JVM 里面去。
2.2、具体debug流程以及图片展示
2.2.1、Enchancer
类 创建对象 Enhancer enhancer = new Enhancer()
EnhancerKey
作为参数传递给 KeyFactory.create(...)
方法
gen.create()
方法执行, 用于创建 Enhancer的代理对象
gen
对象是 KeyFactory
类生成的对象
KeyFactory
父类是 KeyFactory$Generator@482
- 执行
KeyFactory$Generator@482
对象的create
方法(super.create(keyInterface.getName()))
- 执行
new ClassLoaderData(loader)
--> 其实这里面就是包装了两个函数式的接口, 在这边还没开始调用。
- 执行
data.get(...)
注意的是, 这里的 data
就是我们上面通过 new ClassLoaderData(...)
生成的对象。
- 执行
generatedClassses.get(gen)
, 注意这里的 generatedClasses
是一个缓存对象LoadCache
对象。
- 跳出
apply
方法后, 执行 this.createEntry(key, cacheKey, v)
- 通过
task.run()
-> FutureTask
对象的 call
方法 --> Func函数式接口对象的load.apply
方法。
- 如下图所示,
gen.generate(...)
这就是正儿八经的生成字节码文件地方了。
- 执行
gen.generate()
生成器的生成方法
- 有了名字之后就开始生成字节码文件了 ,执行
byte[] b = strategy.generate(this);
// 该方法为字节码写入方法 为最后一步
public void generateClass(ClassVisitor v) {
// 创建类写入聚合对象, 创建的就是一个class文件的写入器
ClassEmitter ce = new ClassEmitter(v);
//找到被代理类的newInstance方法 如果没有会报异常,由此可知,如果想用Generator代理类生成器,必须要有newInstance方法
Method newInstance = ReflectUtils.findNewInstance(keyInterface);
//如果被代理类的newInstance不为Object则报异常,此处我们代理的Enchaer.EnhancerKey newInstance方法返回值为Object
if (!newInstance.getReturnType().equals(Object.class)) {
throw new IllegalArgumentException("newInstance method must return Object");
}
// 找到newInstance方法的所有参数类型并当做成员变量
Type[] parameterTypes = TypeUtils.getTypes(newInstance.getParameterTypes());
// 1.创建类开始写入类头,版本号,访问权限,类名等通用信息
ce.begin_class(Constants.V1_8,
Constants.ACC_PUBLIC,
getClassName(),
KEY_FACTORY,
new Type[]{Type.getType(keyInterface)},
Constants.SOURCE_FILE);
// 2.写入无参构造方法
EmitUtils.null_constructor(ce);
// 3.写入newInstance方法
EmitUtils.factory_method(ce, ReflectUtils.getSignature(newInstance));
int seed = 0;
// 4.开始构造有参构造方法
CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC,
TypeUtils.parseConstructor(parameterTypes),
null);
e.load_this();
// 4.1有参构造中调用父类构造方法,即super.构造方法()
e.super_invoke_constructor();
e.load_this();
// 4.2找到传入的定制器 例如一开始传入的hashCode方法定制器
List<FieldTypeCustomizer> fieldTypeCustomizers = getCustomizers(FieldTypeCustomizer.class);
// 4.3遍历成员变量即newInstance方法的所有参数
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();
// 4.3将这些参数全部声明到写入类中
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);
}
// 4.4设置每个成员变量的值 即我们常见的有参构造中的this.xx = xx
e.putfield(getFieldName(i));
}
// 设置返回值
e.return_value();
// 有参构造及成员变量写入完成
e.end_method();
// hash code
// 5.写入hashcode方法
e = ce.begin_method(Constants.ACC_PUBLIC, HASH_CODE, null);
int hc = (constant != 0) ? constant : PRIMES[(Math.abs(seed) % PRIMES.length)];
int hm = (multiplier != 0) ? multiplier : PRIMES[(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();
// hashcode方法结束
e.end_method();
// equals
// 6.写入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(CodeEmitter.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();
// equals方法结束
e.end_method();
// toString
// 7.写入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();
// toString方法结束
e.end_method();
// 类写入结束,至此类信息收集完成并全部写入ClassVisitor
ce.end_class();
}
- 上面就已经生成了字节码, 下面就是返回到调用方法去, 继续执行:
- 1、将
gen
生成器对象加载到内存中去
- 2、返回生成器对象。
- 最终返回到
data.get(...)
, 生成一个 obj
,然后判断是否是 Class
,如果是 , 就进行实例化
- 至此,上面这一坨, 都是因为我们在创建
enhancer
对象的时候, 需要使用到enhancerKey的一个代理对象, 因此, 上面这边结束,会生成的是一个 enhancerKeY
的一个代理的对象。
- 下面就是通过
Enhancer enhancer = new Enhancer()
生成enhancer
对象 (非代理对象)
- ps:
EnhancerKey
这个代理对象中, 有一个 newInstance
方法, 后面需要使用
2.2.2、MyCalculator
动态代理类的创建
package com.mashibing.proxy.cglib;
import org.springframework.cglib.core.DebuggingClassWriter;
import org.springframework.cglib.proxy.Enhancer;
public class MyTest {
public static void main(String[] args) {
//动态代理创建的class文件存储到本地
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY,"d:\\code");
//通过cglib动态代理获取代理对象的过程,创建调用的对象,在后续创建过程中EnhanceKey的对象,所以在进行enhancer对象创建的时候需要把EnhancerKey(newInstance)对象准备好,恰好这个对象也需要动态代理来生成
Enhancer enhancer = new Enhancer();
//设置enhancer对象的父类
enhancer.setSuperclass(MyCalculator.class);
//设置enhancer的回调对象
enhancer.setCallback(new MyCglib());
//创建代理对象
MyCalculator myCalculator = (MyCalculator) enhancer.create();
//通过代理对象调用目标方法
myCalculator.add(1,1);
System.out.println(myCalculator.getClass());
}
}
- 下面就是创建
MyCalculator
动态代理对象了, 入口语句 MyCalculator myCalculator = (MyCalculator) enhancer.create();
- 调用父类即AbstractClassGenerator的创建代理类(``MyCalculator
) -->
Object result = super.create(key);`
- 最终又走到了
AbstractClassGenerator
中的create
方法 。--> 和之前创建 EnhancerKey 代理对象执行相同的方法。
- 不一样的是 ,由于已经创建过 KEY_FACTORY (EnhancerKey) 的代理预想, 所以, 此时
CACHE
已经不为空了。
- 下面就是和 生成
EnhancerKey
一样的执行步骤
- 这里需要注意的是:
- 此时, 由于生成 的obj 不是 Class字节码文件, 所以, 不需要 执行
firstInstance(...)
,而是执行nextInstance(obj)
;