一、简介
CGLib(Code Generation Library)是一个高性能的字节码生成库,可以在运行期扩展Java类和接口。
实现原理:利用ASM(直接操作字节码的框架)加载被代理类的class文件,修改字节码生成继承自被代理类的子类(代理类),代理类通过重写被代理类方法实现代理。
限制:
- 无法代理被final修饰的类或方法
二、实现CGLib动态代理的Demo
1.被代理类
public class PrintService {
public void print(){
System.out.println("打印信息");
}
}
2.实现MethodInterceptor接口
package com.dotwait.proxy.interceptor;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class UserMethodInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
doBefore();
Object result = methodProxy.invokeSuper(obj, args);
doAfter();
return result;
}
private void doBefore(){
System.out.println("CGLIB动态代理:方法执行前");
}
private void doAfter(){
System.out.println("CGLIB动态代理:方法执行后");
}
}
3.测试
package com.dotwait.proxy;
import com.dotwait.proxy.interceptor.UserMethodInterceptor;
import com.dotwait.proxy.service.PrintService;
import net.sf.cglib.core.DebuggingClassWriter;
import net.sf.cglib.proxy.Enhancer;
public class CGLibProxyApp {
public static void main(String[] args) {
//代理类class文件存入本地磁盘本项目目录下
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, System.getProperty("user.dir"));
//实例化Enhancer类生成器
Enhancer enhancer = new Enhancer();
//设置Enhancer要生成的目标类的父类
enhancer.setSuperclass(PrintService.class);
//设置目标类执行方法的拦截器
enhancer.setCallback(new UserMethodInterceptor());
//获取代理对象
PrintService proxy= (PrintService) enhancer.create();
proxy.print();
}
}
4.执行结果
CGLIB动态代理:方法执行前
打印信息
CGLIB动态代理:方法执行后
三、分析
(1)获取代理对象调用了enhancer.create方法,实现如下
public Object create() {
classOnly = false;
argumentTypes = null;
return createHelper();
}
(2)create方法重置了两个变量后调用了createHelper方法,查看createHelper实现
private Object createHelper() {
// 预声明回调方法的验证
preValidate();
// 构建一个对这类增强操作唯一定位的 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;
// 调用父类的 create(...) 方法
Object result = super.create(key);
return result;
}
(3)createHelper关键逻辑调用了父类的create,实现如下
protected Object create(Object key) {
try {
// 获取加载生成类的ClassLoader
ClassLoader loader = getClassLoader();
// 从缓存中拿到ClassLoader加载过的数据
Map<ClassLoader, ClassLoaderData> cache = CACHE;
ClassLoaderData data = cache.get(loader);
// 缓存中不存在,则将该ClassLoader的数据加入缓存
if (data == null) {
synchronized (AbstractClassGenerator.class) {
// 进入同步代码块后再次确认缓存中无此ClassLoader对应数据
cache = CACHE;
data = cache.get(loader);
if (data == null) {
// 新建缓存,拷贝原有数据,初始化该ClassLoader的数据,加入缓存
Map<ClassLoader, ClassLoaderData> newCache = new WeakHashMap<ClassLoader, ClassLoaderData>(cache);
data = new ClassLoaderData(loader);
newCache.put(loader, data);
CACHE = newCache;
}
}
}
this.key = key;
// 获取代理类的Class对象或ClassLoaderData对象
Object obj = data.get(this, getUseCache());
if (obj instanceof Class) {
// 初次实例化对象
return firstInstance((Class) obj);
}
// 从ClassLoaderData中实例化
return nextInstance(obj);
} catch (RuntimeException e) {
throw e;
} catch (Error e) {
throw e;
} catch (Exception e) {
throw new CodeGenerationException(e);
}
}
(4)data.get是真正获取代理类的Class对象或ClassLoaderData对象的方法,获取到之后Class对象则通过firstInstance实例化,ClassLoaderData对象则通过nextInstance实例化,查看比较核心的data.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);
}
}
(5)gen.generate方法会生成代理类的Class对象,不使用缓存直接调用创建,使用缓存,最终也会调用此方法,因为gen.generate方法的调用存在于ClassLoaderData构造器的Function函数式实例中,gen.generate实现如下
protected Class generate(ClassLoaderData data) {
Class gen;
Object save = CURRENT.get();
CURRENT.set(this);
try {
// 获取类加载器
ClassLoader classLoader = data.getClassLoader();
if (classLoader == null) {
throw new IllegalStateException("ClassLoader is null while trying to define class " +
getClassName() + ". It seems that the loader has been expired from a weak reference somehow. " +
"Please file an issue at cglib's issue tracker.");
}
synchronized (classLoader) {
// 为代理类生成唯一类名
String name = generateClassName(data.getUniqueNamePredicate());
data.reserveName(name);
this.setClassName(name);
}
if (attemptLoad) {
// 尝试直接加载
try {
gen = classLoader.loadClass(getClassName());
return gen;
} catch (ClassNotFoundException e) {
// ignore
}
}
// 通过特定策略实现的形式生成新的字节码
byte[] b = strategy.generate(this);
// 解析新的字节码,获取类的className
String className = ClassNameReader.getClassName(new ClassReader(b));
ProtectionDomain protectionDomain = getProtectionDomain();
synchronized (classLoader) {
// 通过反射加载代理类
if (protectionDomain == null) {
gen = ReflectUtils.defineClass(className, b, classLoader);
} else {
gen = ReflectUtils.defineClass(className, b, classLoader, protectionDomain);
}
}
return gen;
} catch (Exception e) {
throw new CodeGenerationException(e);
} finally {
CURRENT.set(save);
}
}
(6)核心代码是strategy.genereate方法,该方法生成了代理类的字节码,拿到字节码后通过反射工具类ReflectUtils的defineClass加载代理类,查看strategy.genereate方法实现
public byte[] generate(ClassGenerator cg) throws Exception {
DebuggingClassWriter cw = getClassVisitor();
// 生成字节码
transform(cg).generateClass(cw);
return transform(cw.toByteArray());
}
(7)generateClass方法是真正的生成字节码,实现如下
public void generateClass(ClassVisitor v) throws Exception {
Class sc = (superclass == null) ? Object.class : superclass;
// 父类不可以被final修饰
if (TypeUtils.isFinal(sc.getModifiers()))
throw new IllegalArgumentException("Cannot subclass final class " + sc.getName());
// 获取父类直接声明的构造方法
List constructors = new ArrayList(Arrays.asList(sc.getDeclaredConstructors()));
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();
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) {
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());
e.declare_field(Constants.ACC_PRIVATE, BOUND_FIELD, Type.BOOLEAN_TYPE, null);
e.declare_field(Constants.ACC_PUBLIC | Constants.ACC_STATIC, FACTORY_DATA_FIELD, OBJECT_TYPE, null);
if (!interceptDuringConstruction) {
e.declare_field(Constants.ACC_PRIVATE, CONSTRUCTED_FIELD, Type.BOOLEAN_TYPE, null);
}
e.declare_field(Constants.PRIVATE_FINAL_STATIC, THREAD_CALLBACKS_FIELD, THREAD_LOCAL, null);
e.declare_field(Constants.PRIVATE_FINAL_STATIC, STATIC_CALLBACKS_FIELD, CALLBACK_ARRAY, null);
if (serialVersionUID != null) {
e.declare_field(Constants.PRIVATE_FINAL_STATIC, Constants.SUID_FIELD_NAME, Type.LONG_TYPE, serialVersionUID);
}
for (int i = 0; i < callbackTypes.length; i++) {
e.declare_field(Constants.ACC_PRIVATE, getCallbackField(i), callbackTypes[i], null);
}
// This is declared private to avoid "public field" pollution
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);
}
emitSetThreadCallbacks(e);
emitSetStaticCallbacks(e);
emitBindCallbacks(e);
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();
}
(8)第(3)步中的firstInstance和nextInstance的实现如下
protected Object firstInstance(Class type) throws Exception {
if (classOnly) {
return type;
} else {
return createUsingReflection(type);
}
}
protected Object nextInstance(Object instance) {
EnhancerFactoryData data = (EnhancerFactoryData) instance;
if (classOnly) {
return data.generatedClass;
}
Class[] argumentTypes = this.argumentTypes;
Object[] arguments = this.arguments;
if (argumentTypes == null) {
argumentTypes = Constants.EMPTY_CLASS_ARRAY;
arguments = null;
}
return data.newInstance(argumentTypes, arguments, callbacks);
}
(9)最后,都是通过ReflectUtils.newInstance来实例化代理类
private Object createUsingReflection(Class type) {
setThreadCallbacks(type, callbacks);
try{
if (argumentTypes != null) {
return ReflectUtils.newInstance(type, argumentTypes, arguments);
} else {
return ReflectUtils.newInstance(type);
}
}finally{
// clear thread callbacks to allow them to be gc'd
setThreadCallbacks(type, null);
}
}
public Object newInstance(Class[] argumentTypes, Object[] arguments, Callback[] callbacks) {
setThreadCallbacks(callbacks);
try {
// Explicit reference equality is added here just in case Arrays.equals does not have one
if (primaryConstructorArgTypes == argumentTypes ||
Arrays.equals(primaryConstructorArgTypes, argumentTypes)) {
// If we have relevant Constructor instance at hand, just call it
// This skips "get constructors" machinery
return ReflectUtils.newInstance(primaryConstructor, arguments);
}
// Take a slow path if observing unexpected argument types
return ReflectUtils.newInstance(generatedClass, argumentTypes, arguments);
} finally {
// clear thread callbacks to allow them to be gc'd
setThreadCallbacks(null);
}
}
四、代理类反编译
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package com.dotwait.proxy.service;
import java.lang.reflect.Method;
import net.sf.cglib.core.ReflectUtils;
import net.sf.cglib.core.Signature;
import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.Factory;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
/**
* 新的类名,通过 $$EnhancerByCGLIB 以及 $$133b414e(这个是哈希值) 对类名进行唯一区分
* 如果还是重复了,在动态生成前会进行类名的检测,并通过增加序号 "_<index>" 的形式进行进一步区分
*/
public class PrintService$$EnhancerByCGLIB$$133b414e extends PrintService implements Factory {
private boolean CGLIB$BOUND;
public static Object CGLIB$FACTORY_DATA;
private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
private static final Callback[] CGLIB$STATIC_CALLBACKS;
private MethodInterceptor CGLIB$CALLBACK_0;
private static Object CGLIB$CALLBACK_FILTER;
// 被代理类的print方法
private static final Method CGLIB$print$0$Method;
// 代理类的print方法
private static final MethodProxy CGLIB$print$0$Proxy;
private static final Object[] CGLIB$emptyArgs;
private static final Method CGLIB$equals$1$Method;
private static final MethodProxy CGLIB$equals$1$Proxy;
private static final Method CGLIB$toString$2$Method;
private static final MethodProxy CGLIB$toString$2$Proxy;
private static final Method CGLIB$hashCode$3$Method;
private static final MethodProxy CGLIB$hashCode$3$Proxy;
private static final Method CGLIB$clone$4$Method;
private static final MethodProxy CGLIB$clone$4$Proxy;
// 初始化工作,每个方法对象绑定类的实际方法
static void CGLIB$STATICHOOK1() {
CGLIB$THREAD_CALLBACKS = new ThreadLocal();
CGLIB$emptyArgs = new Object[0];
Class var0 = Class.forName("com.dotwait.proxy.service.PrintService$$EnhancerByCGLIB$$133b414e");
Class var1;
CGLIB$print$0$Method = ReflectUtils.findMethods(new String[]{"print", "()V"}, (var1 = Class.forName("com.dotwait.proxy.service.PrintService")).getDeclaredMethods())[0];
CGLIB$print$0$Proxy = MethodProxy.create(var1, var0, "()V", "print", "CGLIB$print$0");
Method[] var10000 = ReflectUtils.findMethods(new String[]{"equals", "(Ljava/lang/Object;)Z", "toString", "()Ljava/lang/String;", "hashCode", "()I", "clone", "()Ljava/lang/Object;"}, (var1 = Class.forName("java.lang.Object")).getDeclaredMethods());
CGLIB$equals$1$Method = var10000[0];
CGLIB$equals$1$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$1");
CGLIB$toString$2$Method = var10000[1];
CGLIB$toString$2$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/String;", "toString", "CGLIB$toString$2");
CGLIB$hashCode$3$Method = var10000[2];
CGLIB$hashCode$3$Proxy = MethodProxy.create(var1, var0, "()I", "hashCode", "CGLIB$hashCode$3");
CGLIB$clone$4$Method = var10000[3];
CGLIB$clone$4$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/Object;", "clone", "CGLIB$clone$4");
}
final void CGLIB$print$0() {
super.print();
}
// 对print方法进行了代理
public final void print() {
// 获取CallBack实例
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
// 为null则尝试重新获取
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
if (var10000 != null) {
// 调用MethodInterceptor的intercept方法,执行增强后的逻辑
// 这里调用的是UserMethodInterceptor的intercept
var10000.intercept(this, CGLIB$print$0$Method, CGLIB$emptyArgs, CGLIB$print$0$Proxy);
} else {
// 为null调用父类PrintService的print,不做代理
super.print();
}
}
final boolean CGLIB$equals$1(Object var1) {
return super.equals(var1);
}
public final boolean equals(Object var1) {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
if (var10000 != null) {
Object var2 = var10000.intercept(this, CGLIB$equals$1$Method, new Object[]{var1}, CGLIB$equals$1$Proxy);
return var2 == null ? false : (Boolean)var2;
} else {
return super.equals(var1);
}
}
final String CGLIB$toString$2() {
return super.toString();
}
public final String toString() {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
return var10000 != null ? (String)var10000.intercept(this, CGLIB$toString$2$Method, CGLIB$emptyArgs, CGLIB$toString$2$Proxy) : super.toString();
}
final int CGLIB$hashCode$3() {
return super.hashCode();
}
public final int hashCode() {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
if (var10000 != null) {
Object var1 = var10000.intercept(this, CGLIB$hashCode$3$Method, CGLIB$emptyArgs, CGLIB$hashCode$3$Proxy);
return var1 == null ? 0 : ((Number)var1).intValue();
} else {
return super.hashCode();
}
}
final Object CGLIB$clone$4() throws CloneNotSupportedException {
return super.clone();
}
protected final Object clone() throws CloneNotSupportedException {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
return var10000 != null ? var10000.intercept(this, CGLIB$clone$4$Method, CGLIB$emptyArgs, CGLIB$clone$4$Proxy) : super.clone();
}
public static MethodProxy CGLIB$findMethodProxy(Signature var0) {
String var10000 = var0.toString();
switch(var10000.hashCode()) {
case -1166389848:
if (var10000.equals("print()V")) {
return CGLIB$print$0$Proxy;
}
break;
case -508378822:
if (var10000.equals("clone()Ljava/lang/Object;")) {
return CGLIB$clone$4$Proxy;
}
break;
case 1826985398:
if (var10000.equals("equals(Ljava/lang/Object;)Z")) {
return CGLIB$equals$1$Proxy;
}
break;
case 1913648695:
if (var10000.equals("toString()Ljava/lang/String;")) {
return CGLIB$toString$2$Proxy;
}
break;
case 1984935277:
if (var10000.equals("hashCode()I")) {
return CGLIB$hashCode$3$Proxy;
}
}
return null;
}
public PrintService$$EnhancerByCGLIB$$133b414e() {
CGLIB$BIND_CALLBACKS(this);
}
public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] var0) {
CGLIB$THREAD_CALLBACKS.set(var0);
}
public static void CGLIB$SET_STATIC_CALLBACKS(Callback[] var0) {
CGLIB$STATIC_CALLBACKS = var0;
}
private static final void CGLIB$BIND_CALLBACKS(Object var0) {
PrintService$$EnhancerByCGLIB$$133b414e var1 = (PrintService$$EnhancerByCGLIB$$133b414e)var0;
if (!var1.CGLIB$BOUND) {
var1.CGLIB$BOUND = true;
Object var10000 = CGLIB$THREAD_CALLBACKS.get();
if (var10000 == null) {
var10000 = CGLIB$STATIC_CALLBACKS;
if (var10000 == null) {
return;
}
}
var1.CGLIB$CALLBACK_0 = (MethodInterceptor)((Callback[])var10000)[0];
}
}
public Object newInstance(Callback[] var1) {
CGLIB$SET_THREAD_CALLBACKS(var1);
PrintService$$EnhancerByCGLIB$$133b414e var10000 = new PrintService$$EnhancerByCGLIB$$133b414e();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
}
public Object newInstance(Callback var1) {
CGLIB$SET_THREAD_CALLBACKS(new Callback[]{var1});
PrintService$$EnhancerByCGLIB$$133b414e var10000 = new PrintService$$EnhancerByCGLIB$$133b414e();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
}
public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) {
CGLIB$SET_THREAD_CALLBACKS(var3);
PrintService$$EnhancerByCGLIB$$133b414e var10000 = new PrintService$$EnhancerByCGLIB$$133b414e;
switch(var1.length) {
case 0:
var10000.<init>();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
default:
throw new IllegalArgumentException("Constructor not found");
}
}
public Callback getCallback(int var1) {
CGLIB$BIND_CALLBACKS(this);
MethodInterceptor var10000;
switch(var1) {
case 0:
var10000 = this.CGLIB$CALLBACK_0;
break;
default:
var10000 = null;
}
return var10000;
}
public void setCallback(int var1, Callback var2) {
switch(var1) {
case 0:
this.CGLIB$CALLBACK_0 = (MethodInterceptor)var2;
default:
}
}
public Callback[] getCallbacks() {
CGLIB$BIND_CALLBACKS(this);
return new Callback[]{this.CGLIB$CALLBACK_0};
}
public void setCallbacks(Callback[] var1) {
this.CGLIB$CALLBACK_0 = (MethodInterceptor)var1[0];
}
static {
CGLIB$STATICHOOK1();
}
}
五、流程
- 调用enhander的create方法创建代理类对象
- 实际调用了父类AbstractClassGenerator的create方法来创建
- create方法中调用ClassLoaderData的get方法获取代理类的Class对象或ClassLoaderData对象
- Class对象的获取先调用GeneratorStrategy的generate方法生成代理类的字节码
- 拿到字节码后,调用RefectUtils的defineClass方法通过代理类的字节码生成Class对象
- 在实例化代理类的处理中,如果拿到的是Class对象则调用firstInstance,否则是ClassLoaderData对象则调用nextInstance进行实例化
- firstInstance和nextInstance最终都是调用RefectUtils的newInstance方法实例化代理类
六、总结
- CGLib动态代理与JDK动态代理形成了互补,对于没有实现接口的类提供了代理方案
- JDK动态代理中调用被代理对象的方法使用的是反射,CGLib动态代理中使用了FastClass机制,该机制避免了反射调用慢的问题,性能上有更好的提升