cglib 动态代理详解
我们都知道jdk的动态代理内部调用切面无效的问题,而cglib则不会出现这种情况,这是为什么?cglib就一定不会出现内部调用切面无效的问题吗?cglib针对每一个类只创建了一个代理类吗?为什么cglib的效率要比jdk的动态代理低呢?
首先我们看一下通常我们是如何使用cglib增强一个类的
public class Main {
static class Test{
public void test(){
System.out.println("test");
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
innerTest();
}
public void innerTest(){
System.out.println("inner test");
}
}
public static void main(String[] args) throws Exception {
Enhancer enhancer = new Enhancer();
// 设置被代理的类
enhancer.setSuperclass(Test.class);
// 创建MethodInterceptor对象作为回调方法
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy)
throws Throwable {
long cost = System.currentTimeMillis();
// 调用实际方法,也就是被代理类原本的方法
Object result = methodProxy.invokeSuper(proxy, args);
System.out.println("method " + method.getName() + " cost time :" + (System.currentTimeMillis() - cost));
return result;
}
});
// 生成代理类,并创建代理类对象
Test test = (Test)enhancer.create();
// 调用代理类对象的方法
test.test();
}
}
输出结果
test
inner test
method innerTest cost time :0
method test cost time :1012
结果完全符合我们的预期,内部调用的函数也被增强了,那我们接下来就一步步的看一下,cglib究竟是如何实现动态代理的。
1. cglib生成的代理类长什么样?
我们先看一下cglib是如何创建一个代理类的,从我们代码中调用的net.sf.cglib.proxy.Enhancer#create()方法开始一层层的往下看
// net.sf.cglib.proxy.Enhancer#create
// 我们创建代理类的入口
public Object create() {
classOnly = false;
argumentTypes = null;
return createHelper();
}
// net.sf.cglib.proxy.Enhancer#createHelper
private Object createHelper() {
// 预处理,验证是否有明确的回调信息
preValidate();
// 存储类信息、回调方法信息等,cglib使用这些信息对象作为缓存key;之后可以根据key直接去缓存中查找创建过的代理类
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;
}
// 父类的create方法,创建代理类并获取代理类对象
// net.sf.cglib.core.AbstractClassGenerator#create
protected Object create(Object key) {
try {
ClassLoader loader = getClassLoader();
/**
* 省略从缓存中获取对象的代码
*/
this.key = key;
// 从缓存中获取代理类的Class对象
Object obj = data.get(this, getUseCache());
if (obj instanceof Class) {
// 使用代理类的Class对象进行实例化
return firstInstance((Class) obj);
}
return nextInstance(obj);
} catch (RuntimeException e) {
// 省略异常处理代码
......
}
}
// 如果使用缓存,则从缓存中取,若不存在则先生成代理类;如果不使用缓存则直接创建
// net.sf.cglib.core.AbstractClassGenerator.ClassLoaderData#get
public Object get(AbstractClassGenerator gen, boolean useCache) {
if (!useCache) {
// 创建代理类并生成对象
return gen.generate(ClassLoaderData.this);
} else {
Object cachedValue = generatedClasses.get(gen);
return gen.unwrapCachedValue(cachedValue);
}
}
// 生成代理类并创建代理对象的核心代码;cglib所有的代理类都从这里创建
// net.sf.cglib.core.AbstractClassGenerator#generate
protected Class generate(ClassLoaderData data) {
Class gen;
Object save = CURRENT.get();
CURRENT.set(this);
try {
// 获取类加载器
ClassLoader classLoader = data.getClassLoader();
....
synchronized (classLoader) {
// 生成代理类的类名
String name = generateClassName(data.getUniqueNamePredicate());
data.reserveName(name);
this.setClassName(name);
}
// 生成代理类的字节码;
// 若想获取生成的代理类的字节码信息可以在此打断点,将字节数据输出到本地文件中,之后所有获取的代理类字节码信息均采用此方法
byte[] b = strategy.generate(this);
String className = ClassNameReader.getClassName(new ClassReader(b));
ProtectionDomain protectionDomain = getProtectionDomain();
synchronized (classLoader) {
// 将字节码转换