在前面的文章(CGLIB原理简析-前篇)中,我们已经弄清楚了代理对象使用相关代理逻辑,本篇文章将逐步揭开代理类生成及实例化的过程。
在大部分场景下,我们使用CGLIB获取动态代理对象的基本代码如下:
MyMethodInterceptor myMethodInterceptor = new MyMethodInterceptor();
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(Student.class);
enhancer.setCallback(myMethodInterceptor);
Student stu = (Student) enhancer.create();
stu.outStudentName();
可以看到,Enhancer就是创建代理对象的关键类型。因此,本文第一章节主要分析Enhancer的构成和功能。为了对Enhancer类有个大概的印象,下面先给出Enhancer源码注释【翻译】:
- Enhancer会生成能够实现方法拦截的动态子类。Enhancer类最初是为了作为JDK Proxy代理的替代方案,但是Enhancer能够代理具体实现类,而不仅仅是实现接口。生成的子类会重写所有被代理类非final方法,并且使用者可以自定义方法拦截器实现方法拦截。
- 其中,最原始、最常用的回调对象类型是MethodInterceptor。在切面(AOP)领域中,MethodInterceptor能够实现环绕通知的能力。基于环绕通知能力,你可以在调用被代理方法的前后穿插执行自定义行为。不仅如此,你也可以改变方法的入参数值,甚至根本不调用被代理方法。
- 尽管MethodInterceptor已经足够通用且能满足任何代理的需要,回调对象还有其他可用类型,比如LazyLoader,目的是为了更加简化或具备更好的性能。常常一个增强子类只会使用一个回调对象,但是你也可以通过CallbackFilter来控制不同方法使用不同回调对象。
- 在CGLIB包下很多类都有类似设计。这些类会提供一些静态方法提供给外界使用,但是为了更好的控制对象,比如控制Enhancer生成子类的自定义类加载器,就需要使用Enhancer的构造器。
- 所有的Enhancer生成的增强子类都会实现Factory接口,当然你也可以通过setUseFactory方法使得子类不实现Factory接口。Factory提供了一些API,可用于修改代理对象的回调对象,也提供了更快、更容易的方式生成一个代理对象。
不着急,我们先来看下Enhancer的类间关系:
public class Enhancer extends AbstractClassGenerator
...
}
Enhancer类仅继承一个抽象类AbstractClassGenerator。AbstractClassGenerator抽象类在cglib包下处于十分关键的位置,几乎任何动态生成字节码的功能类都继承该抽象类,Enhancer仅仅是一个用于生成动态增强子类信息的AbstractClassGenerator具体实现子类,有关AbstractClassGenerator本节第二章会详细叙述。
从类间关系上&功能看,Enhancer类职责实际上是运行时动态生成增强子类字节码的类。这个概念我认为十分重要,不要一股脑扎进“代理”概念中,Enhancer(或者我们说的cglib代理)更切合的理解是“增强。
Enhancer类的属性十分多,这里仅列出与增强子类相关的对象属性,而ASM生成字节码相关的静态类变量在类加载时就初始化了,不涉及复杂逻辑。
private Class[] interfaces; // 增强子类实现的接口列表
private CallbackFilter filter; // 根据filter根据方法选择不同回调对象
private Callback[] callbacks; // 回调对象列表
private Type[] callbackTypes; // 回调对象类型列表
private boolean validateCallbackTypes; // 是否已确定回调对象类型列表标识
private boolean classOnly; // 是否仅返回Class对象,而不是实例化对象
private Class superclass; // 增强子类继承的父类
private Class[] argumentTypes; // 父类构造器类型列表
private Object[] arguments; // 父类构造器入参值
private boolean useFactory = true; // 增强子类是否实现Factory接口
private Long serialVersionUID; // 是否支持序列化操作
private boolean interceptDuringConstruction = true; // 是否拦截构造方法
增强子类的生成依靠Enhancer对象的能力。根据Enhancer类源码注释,Enhancer提供了多个静态方法供外界使用:
这三个静态方法逻辑类似,实际上无非是封装了Enhancer对象的创建、属性赋值、创建增强子类对象的过程。下面为最后一个静态方法代码:
public static Object create(Class superclass, Class[] interfaces, CallbackFilter filter, Callback[] callbacks) {
Enhancer e = new Enhancer(); // Enhancer仅有的无参构造方法
e.setSuperclass(superclass); // 设置各个入参
e.setInterfaces(interfaces);
e.setCallbackFilter(filter);
e.setCallbacks(callbacks);
return e.create(); // 创建并返回增强子类对象
}
在前面一个小节,Enhancer对象的属性其实不止这些,因此如果需要对增强代理对象进行其他控制,比如不实现Factory方法,我们就不能使用这些封装后的static方法,就需要手动创建Enhancer对象。
Enhancer e = new Enhancer(); // Enhancer仅有的无参构造方法
e.setSuperclass(type);
e.setCallback(callback);
e.setSerialVersionUID(1111000L);
e.setUseFactory(false); // 设置不实现Factory接口
return e.create(); // 创建并返回增强子类对象
另外,静态方法只能实现对无参构造的父类进行创建增强子类。如果父类为有参构造,就必须使用带入参的create方法。
Enhancer e= new Enhancer();
e.setSuperclass(Employee.class);
e.setCallbacks(new Callback[]{myMethodInterceptor, anotherMethodInterceptor});
e.setCallbackFilter(new MyCallbackFilter());
return e.create(new Class[]{String.class}, new Object[]{"spl"});
不论是使用静态方法,还是自行创建控制创建流程,最后都会调用Enhancer#create(…)创建增强子类对象。
Enhancer对象提供了三个创建create方法:
private Object createHelper() {
preValidate(); // 前置校验
// 通过KeyFactory机制根据父类、接口等关键特征生成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; // 赋值到ACG#key属性,后续缓存类会使用这个属性
// 通过其父类的create()模版方法创建并返回生成类实例。
Object result = super.create(key);
return result;
}
AbstractClassGenerator是cglib包下所有与类字节码生成相关工具类的抽象类。AbstractClassGenerator实际上是一个模版模式,动态生成类字节码的过程封装在create()方法中,并其中提供了许多钩子函数以及供子类实现的基本方法,如自定义类加载器,自定义生成类的类名。除此之外,AbstractClassGenerator还设计了缓存用于提升类字节码生成的效率。
abstract public class AbstractClassGenerator<T>
implements ClassGenerator {
...
}
AbstractClassGenerator类实现了ClassGenerator接口,该接口仅有一个抽象方法generateClass-根据ASM提供的ClassVistor对象生成类。
public interface ClassGenerator {
void generateClass(ClassVisitor v) throws Exception;
}
实际上,AbstractClassGenerator(下文可能会简称为,ACG)并没有实现generateClass方法,都是由其子类进行实现。ACG类仅负责控制结果类的生成过程模版,具体细节不应该由ACG实现。
既然ACG是模版模式实现,那我们这里直攻要害,先来看看AbstractClassGenerator#create()方法的逻辑。
protected Object create(Object key) {
try {
// 1. 获取生成类的类加载器 (内部支持子类自定义默认类加载器)
ClassLoader loader = getClassLoader();
// 2. 缓存 Key为类加载器 value为ClassLoaderData对象
// (内部维护有generatedClasses缓存)
Map<ClassLoader, ClassLoaderData> cache = CACHE;
ClassLoaderData data = cache.get(loader);
if (data == null) {
// 3. 当前类加载器缓存不存在时,DCL初始化对应的ClassLoaderData对象
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; // 4. 将key赋值属性key上
// 5. 通过ClassLoaderData获取生成类对象
Object obj = data.get(this, getUseCache());
if (obj instanceof Class) {
// 6. 如果是Class对象,就创建实例。具体创建过程由子类实现
return firstInstance((Class) obj);
}
// 7. 如果是真实实例对象,就创建另外一个实例。具体创建过程由子类实现。
return nextInstance(obj);
} catch (RuntimeException e) {
throw e;
} catch (Error e) {
throw e;
} catch (Exception e) {
throw new CodeGenerationException(e);
}
}
生成类的标准过程中,静态缓存属性ACG#CACHE类型为Map
ACG#CACHE仅维护了ClassLoader的映射,但具体生成类的创建过程和缓存逻辑还在ClassLoaderData中。
ClassLoaderData是为AbstractClassGenerator的静态内部类,其主要维护了指定类加载器(classLoader)的生成类缓存。
ClassLoaderData共有三个对象属性:
public ClassLoaderData(ClassLoader classLoader) {
if (classLoader == null) { // 必须传入有效类类加载器
throw new IllegalArgumentException("classLoader == null is not yet supported");
}
// 初始化classLoader属性
this.classLoader = new WeakReference<ClassLoader>(classLoader);
/**
* 这里的load就是真正生成类逻辑的函数式变量。
* load会被传入LoadingCache中,在合适的地方触发load内部逻辑获取生成类并缓存起来!
**/
Function<AbstractClassGenerator, Object> load =
new Function<AbstractClassGenerator, Object>() {
public Object apply(AbstractClassGenerator gen) {
// 重点!
Class klass = gen.generate(ClassLoaderData.this);
return gen.wrapCachedClass(klass);
}
};
// 初始化generatedClasses属性,即创建LoadingCache缓存实例
generatedClasses = new LoadingCache<AbstractClassGenerator, Object, Object>(GET_KEY, load);
}
ClassLoaderData的构造初始化很重要,其中classLoder使用弱引用包装的原因前面已经说过了。后续还有两个重点:
ClassLoaderData初始化LoadingCache缓存逻辑:
// 标记① (为后文引用)
generatedClasses = new LoadingCache<AbstractClassGenerator, Object, Object>(GET_KEY, load);
为进一步了解初始化及缓存过程,先看下LoadingCache的类信息和属性:
public class LoadingCache<K, KK, V> {
// 内部的缓存映射
protected final ConcurrentMap<KK, Object> map;
protected final Function<K, V> loader; // 根据第一个类型映射到缓存Value
protected final Function<K, KK> keyMapper; // 根据第一个类型映射到缓存Key
public LoadingCache(Function<K, KK> keyMapper, Function<K, V> loader) {
this.keyMapper = keyMapper;
this.loader = loader;
this.map = new ConcurrentHashMap<KK, Object>();
}
..
}
从LoadingCache接口上看,标记①出代码中,GET_KEY就是根据ACG对象映射为缓存Key,load变量就是根据ACG对象映射为缓存value。load我们上一个小节说了,就是会调用ACG#generate方法生成动态类Class对象。那GET_KEY是啥?
private static final Function<AbstractClassGenerator, Object> GET_KEY = new Function<AbstractClassGenerator, Object>() {
public Object apply(AbstractClassGenerator gen) {
return gen.key;
}
};
GET_KEY同样也是Function实现的引用,内部逻辑十分简单,返回了ACG#key属性。这个属性实乃为隐藏大佬,简单回顾下,这个key是ACG模版方法的唯一入参(这里可参考2.2节),这就意味着ClassLoaderData缓存生成类Class对象的Key实际上由各个ACG实现类对象决定。
对比JDK动态代理的二级缓存,一级Key也是类加载器,二级Key是由接口列表信息hash生成,value也是动态生成的Class对象。
从整体上看,CGLIB也是二级缓存,二级Key就是LoadingCache#map的Key。那在同样的类加载器下,缓存二级Key如何生成才能区分不同的动态Class对象呢?不同于JDK代理Class仅与接口列表相关,根据1.2节,Enhancer影响动态Class对象的属性很多,必须引入一种机制更巧妙、更快的生成唯一Key。那就是KeyFactory!KeyFactory并不打算在本文介绍,后续有时间再补,其实不理解不影响缓存的逻辑,只要知道ACG具体实现类都对应一个Key,在同一类加载器下对应一个动态Class对象。
LoadingCache的结构清楚了,那如何从该缓存对象中获取动态Class类呢?就在其get方法中。
public V get(K key) {
final KK cacheKey = keyMapper.apply(key); // 获取缓存map的Key
Object v = map.get(cacheKey);
if (v != null && !(v instanceof FutureTask)) {
// 如果当前缓存存在且不是FutureTask对象,那就是命中缓存
return (V) v;
}
// 缓存中不存在Key(或Value尚未创建完成),会执行根据loader生成value逻辑
return createEntry(key, cacheKey, v);
}
protected V createEntry(final K key, KK cacheKey, Object v) {
FutureTask<V> task;
boolean creator = false;
if (v != null) {
// Another thread is already loading an instance
/**
* 第三个参数要么为null,要么为FutureTask;
* 后者就意味着另外有个线程正在执行loader生成动态Class逻辑
**/
task = (FutureTask<V>) v;
} else {
/**
* 不存在,先创建FutureTask塞入缓存map中,以免并发线程直接执行class生成逻辑。
* 注意:这里创建的task的结果不一定会执行,具体还要检查putIfAbsent结果。
**/
task = new FutureTask<V>(new Callable<V>() {
public V call() throws Exception {
return loader.apply(key);
}
});
Object prevTask = map.putIfAbsent(cacheKey, task); // 并发安全
if (prevTask == null) {
/**
* map中确实没有task,当前线程的task可以执行,
* 并且需要把最终结果覆盖FutureTask实例
**/
creator = true;
task.run();
} else if (prevTask instanceof FutureTask) {
// 并发线程抢先一步put到缓存map中
task = (FutureTask<V>) prevTask;
} else {
// 并发线程抢先一步将结果put到map中去
return (V) prevTask;
}
}
V result;
try {
result = task.get(); // 阻塞等待task任务执行完成,并返回结果
} catch (InterruptedException e) {
throw new IllegalStateException("Interrupted while loading cache item", e);
} catch (ExecutionException e) {
Throwable cause = e.getCause();
if (cause instanceof RuntimeException) {
throw ((RuntimeException) cause);
}
throw new IllegalStateException("Unable to load cache item", cause);
}
if (creator) {
// 如果当前现成的task执行,结果需要放置到map中覆盖futureTask
map.put(cacheKey, result);
}
return result;
}
LoadingCache缓存的设计十分精彩,相比于JDK代理使用的WeakCache缓存,逻辑简单些。因为WeakCache同时处理二级Key、Value的生成,而LoadingCache只需要处理Value的生成,二级Key交给了具体ACG对象。
代码注释上面写的十分清楚,这里就总结下为什么会引入FutureTask实例作为中间态。因为loader创建Value的逻辑可能十分耗费资源,不使用中间态可能会有多个并发线程通过执行loader创建value的逻辑。而创建FutureTask并设置进缓存map是十分快速的,中间通过putIfAbsent控制并发,就不会出现创建Vlaue逻辑被多次执行的情况。
CGLIB缓存结构基本已经十分清晰了。ACG#cache就是整体的缓存对象,类型为WeakHashMap
ClassLoaderData就是负责类加载器下的缓存,内部实现通过LoadingCache实例管理类加载器下不同条件下生成的动态Class对象,二级Key就是ACG#key属性。
因此,ClassLoaderData必须提供get方法,用于根据二级Key来获取对应的动态Class类对象。代码如下:
public Object get(AbstractClassGenerator gen, boolean useCache) {
if (!useCache) {
// 不使用缓存,就直接通过ACG#generate方法生成(与loader变量引用的逻辑一致)。
return gen.generate(ClassLoaderData.this);
} else {
// 通过LoadingCache实例get方法获取Value,其内部可能会通过loader变量引用的方法创建Value
Object cachedValue = generatedClasses.get(gen);
return gen.unwrapCachedValue(cachedValue); // 褪去缓存value的弱引用包装
}
}
从ACG的模版方法中,是通过ClassLoaderData实例来获取动态生成的Class对象。而在2.2节对ClassLoaderData的缓存机制中,我们可以看到实际内部生成Class对象的实际动作由ACG#generate方法完成。该方法也同样是个模版发方法,代码如下:
protected Class generate(ClassLoaderData data) {
Class gen;
Object save = CURRENT.get();
CURRENT.set(this); // 修改当前线程正在执行生成类的ACG实例
try {
// 1. 获取生成类的类加载器。目前不支持为Null。
ClassLoader classLoader = data.getClassLoader();
if (classLoader == null) {
throw new IllegalStateException("ClassLoader is null Please file an issue at cglib's issue tracker.");
}
synchronized (classLoader) {
// 2. 生成类名,默认保证了类加载器下不能生成重复类名
String name = generateClassName(data.getUniqueNamePredicate());
data.reserveName(name);
this.setClassName(name);
}
/**
* 3. 根据attemptLoad属性值,先尝试使用类加载器加载
* 因为前面生成的类名默认保证在同一类加载器下唯一,这里使用类加载器加载一个新类名,肯定加载不到,因此默认attemptLoad为false。(ps:确实没有必要设置为true)
**/
if (attemptLoad) {
try {
gen = classLoader.loadClass(getClassName());
return gen;
} catch (ClassNotFoundException e) {
// ignore
}
}
// 4. 根据ACG#strategy的策略来生成字节码【重点】
byte[] b = strategy.generate(this);
// 5. 使用ASM底层工具获取类字节码的类名。(generate内部可能修改类名)
String className = ClassNameReader.getClassName(new ClassReader(b));
/** 6. 获取动态生成Class的保护域对象,后续会加载class类时会考虑。
* 内部加载优先使用java.lang.ClassLoader#defineClass加载该类,
* 其次使用sun.misc.Unsafe#defineClass加载该类
**/
ProtectionDomain protectionDomain = getProtectionDomain();
synchronized (classLoader) { // just in case
if (protectionDomain == null) {
// 加载不考虑protectionDomain
gen = ReflectUtils.defineClass(className, b, classLoader);
} else {
// 加载考虑protectionDomain
gen = ReflectUtils.defineClass(className, b, classLoader, protectionDomain);
}
}
return gen;
} catch (RuntimeException e) {
throw e;
} catch (Error e) {
throw e;
} catch (Exception e) {
throw new CodeGenerationException(e);
} finally {
CURRENT.set(save);
}
}
这里大概总结下ACG生成类信息并加载到JVM的标准化流程:
增强子类的类加载器选择顺序:父类加载器>接口类加载器>Ehancer类加载器>线程上下文加载器>异常
ACG动态生成的类名是通过设置的命名策略产生的。使用者可以自定义命名策略,需实现NamingPolicy接口。该接口声明了两个抽象方法,getClassName(…)及equals(…),其中equals方法暂时内部没有使用到,因此我们先看下getClassName(…)方法:
String getClassName(String prefix, String source, Object key, Predicate names);
方法参数含义列举如下:
在CGLIB仅提供了一个NamingPolicy的实现类-DefaultNamingPolicy,也是ACG默认的命名策略。我们看下DefaultNamingPolicy是如何生成类名的:
public String getClassName(String prefix, String source, Object key, Predicate names) {
if (prefix == null) { // prefix为空时默认值
prefix = "net.sf.cglib.empty.Object";
} else if (prefix.startsWith("java")) {
// 这个没太懂有啥特殊的地方,后续再看哈
prefix = "$" + prefix;
}
// 拼接基本类名
String base =
prefix + "$$" +
source.substring(source.lastIndexOf('.') + 1) +
getTag() + "$$" +
Integer.toHexString(STRESS_HASH_CODE ? 0 : key.hashCode());
String attempt = base;
int index = 2;
while (names.evaluate(attempt)) // 重名通过增加数字保证唯一性
attempt = base + "_" + index++;
return attempt;
}
从上述逻辑中看,prefix其实定义了生成类的包名和类名前缀(父类名),然后拼接生成源类的类名,然后拼接命名策略标签,然后拼接类唯一Key的hashCode(STRESS_HASH_CODE,测试模式,不需要关注),然后根据类是否唯一来选择拼接递增数字。
以CGLIB原理简析-前篇第一章示例中,prefix=“com.design.代理模式.cglib.Student”,source=“net.sf.cglib.Enhancer”,DefaultNamingPolicy#getTag=“ByCGLIB”。因此最终生成动态类名为Student$$EnhancerByCGLIB$86327ae0,其中86327ae0为二级Key的hashCode值。
通过类名生成策略的讲解,以后我们在看到CGLIB动态生成类时,从其全限定名就知道该动态类的父类或接口、生成源(由哪个类生成)、是否为默认策略等信息。
- 使用者完全可以实现NamingPolicy接口,并通过setNamingPolicy设置命名策略,因此ACG其实无法保证生成类名的唯一性。如果存在重名的情况下,可以设置attemptLoad为true来尝试加载Class。
- 一定要区分生成类名和最终类名。通过命名策略生成的类名可能有重复,但是在类加载器中的类名一定不会重复。
同样的,ACG动态生成类字节码也是通过设置策略产生的。使用者也可以自定字节码生成策略,需实现GeneratorStrategy接口。该接口也声明了两个抽象方法,generate(…)及equals(…),其中equals方法暂时内部没有使用到,因此我们先看下generate(…)方法:
byte[] generate(ClassGenerator cg) throws Exception;
返回值就是字节码数组,只有唯一的入参是ClassGenerator对象。前面说过ClassGenerator是个接口,ACG就是实现了这个接口,因此一般这里传入的就是ACG的实现类对象。
在CGLIB中也仅提供了一个直接实现GeneratorStrategy接口的实现类-DefaultGeneratorStrategy,也是ACG默认的字节码生成策略。我们看下其generate方法:
public byte[] generate(ClassGenerator cg) throws Exception {
// 1. 获取ClassWriter实例;
// 这里使用的CGLIB继承自ClassWriter的子类DebuggingClassWriter
DebuggingClassWriter cw = getClassVisitor();
// 将ACG实例转换一层,一般是一个代理生成器,如TransformingClassGenerator
transform(cg).generateClass(cw);
// 将生成的字节码数组转换一层。目的就是为了提供拦截的方法。
return transform(cw.toByteArray());
}
实际上,generate也可以认为是模版方法,使用者可以继承DefaultGeneratorStrategy类,并重写两个transform方法在生成字节码动作做一些事情,参考UndeclaredThrowableStrategy。
默认情况下ACG就是DefaultGeneratorStrategy类,两处transform都是直接返回的,因此默认generate方法就是获取ClassWriter示例,并调用ACG实现类的generateClass方法来生成动态字节码(还记得之前说过,ACG实现了ClassGenerator类,但并未实现generateClass方法)。因此如何生成字节码的呢?这个我们要通过ACG的实现子类去看。下一个章节我们就简单聊下Ehancer这个ACG实现类的generateClass方法逻辑。
Ehancer作为重要的ACG实现类,本章节简单聊下其生成动态类信息的过程。
public void generateClass(ClassVisitor v) throws Exception {
// 父类默认设计Object类,要么是用户指定类
Class sc = (superclass == null) ? Object.class : superclass;
if (TypeUtils.isFinal(sc.getModifiers()))
// 检查类不能是final类型,不允许继承
throw new IllegalArgumentException("Cannot subclass final class " + sc.getName());
// 获取父类所有的声明构造器,且默认过滤掉私有构造器
List constructors = new ArrayList(Arrays.asList(sc.getDeclaredConstructors()));
filterConstructors(sc, constructors);
/**
* 获取需要实现或重写的所有的方法actualMethods
* interfaceMethods所有接口方法,forcePublic存储Public方法的签名Key
* getMethods内部会过滤掉静态、私有、final修饰的方法,也会根据方法签名Key去重(KEY_FACTORY)
**/
List actualMethods = new ArrayList();
List interfaceMethods = new ArrayList();
final Set forcePublic = new HashSet();
getMethods(sc, interfaces, actualMethods, interfaceMethods, forcePublic);
// 处理各个方法的权限符
List methods = CollectionUtils.transform(actualMethods, new Transformer() {
public Object transform(Object value) {
Method method = (Method)value;
int modifiers = Constants.ACC_FINAL
| (method.getModifiers()
& ~Constants.ACC_ABSTRACT
& ~Constants.ACC_NATIVE
& ~Constants.ACC_SYNCHRONIZED);
if (forcePublic.contains(MethodWrapper.create(method))) {
modifiers = (modifiers & ~Constants.ACC_PROTECTED) | Constants.ACC_PUBLIC;
}
return ReflectUtils.getMethodInfo(method, modifiers);
}
});
ClassEmitter e = new ClassEmitter(v);
if (currentData == null) {
/**
* 生成类的版本、访问权限、类名、父类类型、接口列表,来源
* useFactory属性决定了生成类是否继承Factory接口
**/
e.begin_class(Constants.V1_8,
Constants.ACC_PUBLIC,
getClassName(),
Type.getType(sc),
(useFactory ?
TypeUtils.add(TypeUtils.getTypes(interfaces), FACTORY) :
TypeUtils.getTypes(interfaces)),
Constants.SOURCE_FILE);
} else {
e.begin_class(Constants.V1_8,
Constants.ACC_PUBLIC,
getClassName(),
null,
new Type[]{FACTORY},
Constants.SOURCE_FILE);
}
// 将构造方法转换为了MethodInfo对象
List constructorInfo = CollectionUtils.transform(constructors, MethodInfoTransformer.getInstance());
// 声明动态类中私有CGLIB$BOUND布尔类型属性
e.declare_field(Constants.ACC_PRIVATE, BOUND_FIELD, Type.BOOLEAN_TYPE, null);
// 声明动态类中公共静态CGLIB$FACTORY_DATA类型为Object属性
e.declare_field(Constants.ACC_PUBLIC | Constants.ACC_STATIC, FACTORY_DATA_FIELD, OBJECT_TYPE, null);
if (!interceptDuringConstruction) {
// 如果设置interceptDuringConstruction属性为false,会声明动态类中私有CGLIB$CONSTRUCTED属性
e.declare_field(Constants.ACC_PRIVATE, CONSTRUCTED_FIELD, Type.BOOLEAN_TYPE, null);
}
// 声明动态类中私有静态final的CGLIB$THREAD_CALLBACKS类型为ThreadLocal属性
e.declare_field(Constants.PRIVATE_FINAL_STATIC, THREAD_CALLBACKS_FIELD, THREAD_LOCAL, null);
// 声明动态类中私有静态final的CGLIB$STATIC_CALLBACKS类型为Callback属性
e.declare_field(Constants.PRIVATE_FINAL_STATIC, STATIC_CALLBACKS_FIELD, CALLBACK_ARRAY, null);
if (serialVersionUID != null) {
// 声明动态类中私有静态final的serialVersionUID类型为Long属性,并赋值serialVersionUID
e.declare_field(Constants.PRIVATE_FINAL_STATIC, Constants.SUID_FIELD_NAME, Type.LONG_TYPE, serialVersionUID);
}
for (int i = 0; i < callbackTypes.length; i++) {
// 声明动态类中私有的CGLIB$CALLBACK_{index}回调类型属性
e.declare_field(Constants.ACC_PRIVATE, getCallbackField(i), callbackTypes[i], null);
}
// 声明动态类中静态私有的CGLIB$CALLBACK_FILTER属性,类型为Object
e.declare_field(Constants.ACC_PRIVATE | Constants.ACC_STATIC, CALLBACK_FILTER_FIELD, OBJECT_TYPE, null);
if (currentData == null) {
// 产生生成类中所有方法
emitMethods(e, methods, actualMethods);
// 产生生成类中所有构造方法
emitConstructors(e, constructorInfo);
} else {
emitDefaultConstructor(e);
}
// 生成公开静态方法CGLIB$SET_THREAD_CALLBACKS()方法
emitSetThreadCallbacks(e);
// 生成公开静态的CGLIB$SET_STATIC_CALLBACKS()方法
emitSetStaticCallbacks(e);
// 生成私有静态final的CGLIB$BIND_CALLBACKS()方法
emitBindCallbacks(e);
/**
* 下面是生成Factory的实现方法
**/
if (useFactory || currentData != null) {
int[] keys = getCallbackKeys();
emitNewInstanceCallbacks(e);
emitNewInstanceCallback(e);
emitNewInstanceMultiarg(e, constructorInfo);
emitGetCallback(e, keys);
emitSetCallback(e, keys);
emitGetCallbacks(e);
emitSetCallbacks(e);
}
e.end_class();
}
这一部分就是Enhancer实际通过ASM框架生成类的逻辑,结合CGLIB原理简析-前篇中对增强代理类公开方法的讲解来看,逻辑还是十分简单的。但是,在实际使用ASM的一些细节上,本文不再继续深追,后续看时间详细聊下ASM相关知识。
至此,Enhancer动态生成代理类信息的过程基本已经十分清楚了。Enhancer实际继承了AbstractClassGenerator抽象类,该抽象类有重要的两个模版方法,分别是: