highlight: arduino-light
Enhancer#create
在我们的测试类中,大家发现了,我们创建了一个Enhancer对象,并且设置了父类、回调函数等参数,最重要的入口函数是create方法。
java /** * 如果必须要创建一个新类,那么就用指定的回调对象创建一个新的对象实例 * 使用的父类的参数的构造方法来实例化父类的部分 */ public Object create() { //不作代理类限制 classOnly = false; //没有构造参数类型 argumentTypes = null; //执行创建 return createHelper(); }
Enhancer#createHelper
java private Object createHelper() { //校验callbackTypes、filter是否为空,以及为空时的处理 preValidate(); //通过EnhancerKey创建key //终于知道为什么叫Enhancerkey并且变量名是KEY_FACTORY。 //原来EnhancerKey是专门用于生成代理类的缓存的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); //设置当前enhancer的key标识 this.currentKey = key; //当前类是Enhancer 父类是AbstractClassGenerator //调用父类即AbstractClassGenerator的创建代理类 Object result = super.create(key); return result; }
AbstractClassGenerator#create
和创建EnhancerKey的代理类一样,最后都调用了AbstractClassGenerator#create方法,不同的是AbstractClassGenerator#create方法的入参key的不同。
EnhancerKey是类的全限定名:net.sf.cglib.proxy.Enhancer$EnhancerKey
而Ehancer创建的代理类的key是由EnhancerKey的代理类创建的。
java //通过EnhancerKey创建的key protected Object create(Object key) { try { //获取到当前生成器的类加载器 ClassLoader loader = getClassLoader(); //CACHE= new WeakHashMap<ClassLoader, ClassLoaderData>(); //CACHE是当前类加载器对应的缓存可以理解为一级缓存 //缓存key为类加载器,缓存的value为ClassLoaderData //ClassLoaderData可以理解为二级缓存 Map<ClassLoader, ClassLoaderData> cache = CACHE; //先根据类加载器从一级缓存中获取对应的ClassLoaderData ClassLoaderData data = cache.get(loader); //如果缓存中的data为空 if (data == null) { synchronized (AbstractClassGenerator.class) { cache = CACHE; data = cache.get(loader); //经典的防止并发修改 二次判断 double check if (data == null) { //新建一个缓存Cache 并把原來的缓存加入新建的缓存中 Map<ClassLoader, ClassLoaderData> newCache = new WeakHashMap<ClassLoader, ClassLoaderData>(cache); //新建一个当前加载器对应的ClassLoaderData 并加到缓存中 //ClassLoaderData#ClassLoaderData data = new ClassLoaderData(loader); //放入新缓存 newCache.put(loader, data); //刷新全局缓存 CACHE = newCache; } } } // 使用创建的key this.key = key; //data:ClassLoaderData //this:Enhancer //getUseCache():可以通过Enhancer.setUseCache()设置 //data是AbstractClassGenerator$ClassLoaderData //返回的是生成好的代理类的class信息 Object obj = data.get(this, getUseCache()); //如果为class则实例化class并返回 就是我们需要的代理类 if (obj instanceof Class) { return firstInstance((Class) obj); } //如果不是则说明是实体 则直接执行另一个方法返回实体 return nextInstance(obj); } catch (RuntimeException e) { throw e; } catch (Error e) { throw e; } catch (Exception e) { throw new CodeGenerationException(e); } }
因为接下来的代码和创建EnhancerKey的代理类的代码都大同小异,所以直接跳过。
不同的地方在于EnhancerKey生成代理类的字节码用的是KeyFactory.Genrator#generateClass(ClassVisitor c)方法。
Enhancer生成代理类的字节码用的是Enhancer#generateClass(ClassVisitor c)方法。
调用generateClass(ClassVisitor c)方法是在DefaultGeneratorStrategy里,直接从这里看。
DefaultGeneratorStrategy#generate
java public byte[] generate(ClassGenerator cg) throws Exception { //创建一个写入器 DebuggingClassWriter cw = getClassVisitor(); //transform是模板方法 //子类可以通过transform方法加入自己的转换逻辑后 //再执行代理类生成器的generateClass方法 transform(cg).generateClass(cw); //将cw写入的东西转换为byte数组返回 return transform(cw.toByteArray()); }
这里面主要是新建一个写入器,然后执行我们代理类生成器的generateClass方法将class信息写入这个ClassWriter 最后将里面的东西转换为byte数组返回,所以又回到了我们的代理类生成器的generateClass方法,这儿进入的是Enhancer的generateClass方法
Enhancer#generatorClass
```java public void generateClass(ClassVisitor v) throws Exception { //需要代理的类或者接口 即 cglib代理.MyCalculator Class sc = (superclass == null) ? Object.class : superclass; //检查 final类无法被继承 if (TypeUtils.isFinal(sc.getModifiers())) throw new IllegalArgumentException ("Cannot subclass final class " + sc.getName()); //找到MyCalculator的所有的构造函数 List constructors = new ArrayList (Arrays.asList(sc.getDeclaredConstructors())); //去掉private之类的不能被继承的构造函数 filterConstructors(sc, constructors);
// Order is very important: must add superclass, then
// its superclass chain, then each interface and
// its superinterfaces.
//这儿顺序非常重要 上面是源码的注释 直接留着 相信大家都能看懂
//声明代理类方法集合
List actualMethods = new ArrayList();
//声明代理接口接口方法集合
List interfaceMethods = new ArrayList();
//声明所有必须为public的方法集合 这儿主要是代理类接口实现的接口的方法
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);
//1.开始创建类 并写入基本信息 如java版本,类修饰符 类名等
if (currentData == null) {
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);
}
//
List constructorInfo = CollectionUtils.transform(constructors, MethodInfoTransformer.getInstance());
//2. 声明一个private boolean 类型的属性:CGLIB$BOUND
e.declare_field(Constants.ACC_PRIVATE, BOUND_FIELD, Type.BOOLEAN_TYPE, null);
//3. 声明一个public static Object 类型的属性:CGLIB$FACTORY_DATA
e.declare_field(Constants.ACC_PUBLIC | Constants.ACC_STATIC,
FACTORY_DATA_FIELD, OBJECT_TYPE, null);
// 这个默认为true
//如果为false则会声明一个private boolean 类型的属性:CGLIB$CONSTRUCTED
if (!interceptDuringConstruction) {
e.declare_field(Constants.ACC_PRIVATE, CONSTRUCTED_FIELD,
Type.BOOLEAN_TYPE, null);
}
//4. 声明一个public static final 的ThreadLocal:CGLIB$THREAD_CALLBACKS
e.declare_field(Constants.PRIVATE_FINAL_STATIC,
THREAD_CALLBACKS_FIELD, THREAD_LOCAL, null);
//5. 声明一个public static final 的CallBack类型的数组:CGLIB$STATIC_CALLBACKS
e.declare_field(Constants.PRIVATE_FINAL_STATIC,
STATIC_CALLBACKS_FIELD,CALLBACK_ARRAY, null);
//如果serialVersionUID不为null
//则设置一个public static final 的Long类型
//serialVersionUID
if (serialVersionUID != null) {
e.declare_field(Constants.PRIVATE_FINAL_STATIC,
Constants.SUID_FIELD_NAME, Type.LONG_TYPE, serialVersionUID);
}
//遍历CallBackTypes 即我们构建Enhancer是setCallBack的所有类的类型
//本案例中是methodInterceptor 并且只传入了一个
for (int i = 0; i < callbackTypes.length; i++) {
//6.声明private修饰 我们自定义的CallBack类型的属性:
//CGLIB$CALLBACK_0 (从0开始编号,)
e.declare_field(Constants.ACC_PRIVATE,
getCallbackField(i), callbackTypes[i], null);
}
//7声明一个private static 的传入的Object类型的属性:CGLIB$CALLBACK_FILTER
e.declare_field(Constants.ACC_PRIVATE | Constants.ACC_STATIC,
CALLBACK_FILTER_FIELD, OBJECT_TYPE, null);
//判断currentData
if (currentData == null) {
//8.如果为null则声明所有的代理类方法的变量
//以及其具体的重写实现方法,还有static初始化执行代码块
emitMethods(e, methods, actualMethods);
//9.声明构造函数
emitConstructors(e, constructorInfo);
} else {
//声明默认构造函数
emitDefaultConstructor(e);
}
//
emitSetThreadCallbacks(e);
emitSetStaticCallbacks(e);
emitBindCallbacks(e);
//如果currentData不为null
if (useFactory || currentData != null) {
//获取到所有CallBack索引数组
int[] keys = getCallbackKeys();
//10.声明三个newInstance方法
//只有一个callback参数
emitNewInstanceCallbacks(e);
//参数为callback数组
emitNewInstanceCallback(e);
//参数为callback数组 以及附带的一些参数
emitNewInstanceMultiarg(e, constructorInfo);
//11.声明getCallBack方法
emitGetCallback(e, keys);
//12.声明setCallBack方法
emitSetCallback(e, keys);
//12.声明setCallBacks方法
emitGetCallbacks(e);
//12.声明setCallBacks方法
emitSetCallbacks(e);
}
//类声明结束
e.end_class();
```
getMethods主要 是获取代理类的所有方法 和 代理类所实现接口的所有方法 用字节码将 所有的方法写到一个代理的类中,
```java private static void getMethods(Class superclass, Class[] interfaces, List methods, List interfaceMethods, Set forcePublic) { // ReflectUtils.addAllMethods(superclass, methods); List target = (interfaceMethods != null) ? interfaceMethods : methods; if (interfaces != null) { for (int i = 0; i < interfaces.length; i++) { if (interfaces[i] != Factory.class) { ReflectUtils.addAllMethods(interfaces[i], target); } } } if (interfaceMethods != null) { if (forcePublic != null) { //这里会触发MethodWrapper类的加载,完成对MethodWrapper.MethodWrapperKey的代理 // MethodWrapper.MethodWrapperKey KEYFACTORY =
// (MethodWrapper.MethodWrapperKey)KeyFactory.create(MethodWrapper.MethodWrapperKey.class); //使用MethodWrapper对所有接口方法创建唯一标识 forcePublic.addAll(MethodWrapper.createSet(interfaceMethods)); } methods.addAll(interfaceMethods); } // 过滤掉静态方法 CollectionUtils.filter(methods, new RejectModifierPredicate(Constants.ACCSTATIC)); // 过滤掉不可见的方法(包括两类:私有方法、默认修饰符且与目标类不在同一个包中的方法) CollectionUtils.filter(methods, new VisibilityPredicate(superclass, true)); // 过滤掉重复的方法(方法名、入参和返回类型都相同的方法) CollectionUtils.filter(methods, new DuplicatesPredicate()); // 过滤掉final方法 CollectionUtils.filter(methods, new RejectModifierPredicate(Constants.ACC_FINAL)); }
```
```java public class MethodWrapper { private static final MethodWrapper.MethodWrapperKey KEY_FACTORY = (MethodWrapper.MethodWrapperKey)KeyFactory.create(MethodWrapper.MethodWrapperKey.class);
private MethodWrapper() {
}
public static Object create(Method method) {
return KEY_FACTORY.newInstance(method.getName(), ReflectUtils.getNames(method.getParameterTypes()), method.getReturnType().getName());
}
public static Set createSet(Collection methods) {
Set set = new HashSet();
Iterator it = methods.iterator();
while(it.hasNext()) {
set.add(create((Method)it.next()));
}
return set;
}
public interface MethodWrapperKey {
Object newInstance(String var1, String[] var2, String var3);
}
} ```
MethodWrapper.MethodWrapperKey的作用是什么呢?
作用是输出方法的方法名、参数类型、返回值,用于比对方法和过滤方法。
java for (Method method : Calculator.class.getMethods()) { System.out.println(MethodWrapper.create(method)); }
输出:
add, {int, int}, int wait,}, void wait, {long, int}, void wait, {long}, void equals, {java.lang.Object}, boolean toString,}, java.lang.String hashCode,}, int getClass,}, java.lang.Class notify,}, void notifyAll,}, void
可以看到这儿也是声明一个写入类 然后按照Ehancer的代理生成策略写入符合的class信息然后返回,最后依旧会执行toByteArray方法返回byte[]数组,这样则又回到了步骤中 根据类加载器 字节码数组来动态将代理类加载进内存中的方法了。最后我们回到根据class获取实例的代码即可返回被代理实例。 而我们执行方法时执行的是代理类中对应的方法,然后调用我们传入的callback执行 原理和jdk动态代理类似,至此 cglib动态代理源码分析到此结束。