前言
上一篇文章我们讲了JDK动态代理及相关源码解析,我们了解了JDK动态代理的基本原理。JDK动态代理只代理接口,而CGLib可以代理任意一个目标类(对final类和方法无法代理),本文我们将探索CGLib如何使用及底层逻辑。
1. CGLib
CGLib (Code Generation Library) 是一个强大,高性能,高质量的Code生成类库。它可以在运行期扩展Java类、实现Java接口。
1.1 代码示例
<!-- https://mvnrepository.com/artifact/cglib/cglib -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
public class Bank {
public void transfer(String transferAmount) {
System.out.println("给目标账户执行转账" + transferAmount + "元···");
}
public void withdraw(String withdrawAmount) {
System.out.println("给客户取款" + withdrawAmount + "元···");
}
}
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class ATM implements MethodInterceptor {
/**
* @param o 代理类
* @param method 拦截的方法
* @param objects 参数数组
* @param methodProxy 对方法的代理
* @return o
*/
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
operation(false);
methodProxy.invokeSuper(o, objects);
operation(true);
return o;
}
private void operation(boolean finishFlag) {
String currentStatus = finishFlag ? "业务处理完毕,收起银行卡。" : "开始业务操作···";
System.out.println(currentStatus);
}
}
import net.sf.cglib.core.DebuggingClassWriter;
import net.sf.cglib.proxy.Enhancer;
public class Consumer {
static {
// 将执行过程中通过cglib动态生成的class文件保存到本地
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "F:\\class");
}
public static void main(String[] args) {
ATM atm = new ATM();
Enhancer enhancer = new Enhancer();
// 设置父类(基于Business生成代理子类)
enhancer.setSuperclass(Bank.class);
// 设置回调
enhancer.setCallback(atm);
Bank business = (Bank) enhancer.create();
business.transfer("200");
business.withdraw("20000000000000");
}
}
开始业务操作···
给目标账户执行转账200元···
业务处理完毕,收起银行卡。
开始业务操作···
给客户取款20000000000000元···
业务处理完毕,收起银行卡。
1.2 源码阅读
1.2.1 CGLib代理类的生成步骤
首先我们先查看Enhancer.create()
主要做了那些事:
// net.sf.cglib.proxy.Enhancer
public class Enhancer extends AbstractClassGenerator{
// 代码部分省略
private static final EnhancerKey KEY_FACTORY =
(EnhancerKey)KeyFactory.create(EnhancerKey.class, KeyFactory.HASH_ASM_TYPE, null);
/** Internal interface, only public due to ClassLoader issues. */
public interface EnhancerKey {
public Object newInstance(String type,
String[] interfaces,
WeakCacheKey<CallbackFilter> filter,
Type[] callbackTypes,
boolean useFactory,
boolean interceptDuringConstruction,
Long serialVersionUID);
}
/**
* 设置被代理的类。
* 如果superclass是一个接口,则使用setInterfaces.
* 非接口实参不能声明为final,并且必须有一个可以访问的构造参数
* @param superclass 被代理的类或接口
*/
public void setSuperclass(Class superclass) {
if (superclass != null && superclass.isInterface()) {
setInterfaces(new Class[]{ superclass });
} else if (superclass != null && superclass.equals(Object.class)) {
this.superclass = null;
} else {
this.superclass = superclass;
}
}
public void setInterfaces(Class[] interfaces) {
this.interfaces = interfaces;
}
/**
* 设置代理类的方法映射到特定回调索引
*/
public void setCallbackFilter(CallbackFilter filter) {
this.filter = filter;
}
/**
* 设置单个回调
*/
public void setCallback(final Callback callback) {
setCallbacks(new Callback[]{ callback });
}
/**
* 设置回调数组。
* 设置该方法的同时必须使用CallbackFilter
* 来指定代理类中每个方法在对应的回调索引。
*/
public void setCallbacks(Callback[] callbacks) {
if (callbacks != null && callbacks.length == 0) {
throw new IllegalArgumentException("Array cannot be empty");
}
this.callbacks = callbacks;
}
/**
* 生成代理类,并使用指定回调。
* @return 返回代理类实例
*/
public Object create() {
classOnly = false;
argumentTypes = null;
return createHelper();
}
private Object createHelper() {
preValidate();
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;
}
// 代码部分省略
}
调用Enhancer.create()
时大致流程如下:
- 调用
createHelper()
方法然后进行前置条件检查; - 调用
Enhancer
内部接口EnhancerKey
的newInstance(···)
生成唯一key
(用于从缓存中获取代理类实例)。 - 然后通过
super.create(key)
获取我们设置的SuperClass对应的代理类实例。
下面我们继续跟进AbstractClassGenerator.create()源码如下:
// net.sf.cglib.core.AbstractClassGenerator
abstract public class AbstractClassGenerator<T> implements ClassGenerator{
// 部分省略
protected Object create(Object key) {
try {
// 获得类加载器 loader作为缓存key
ClassLoader loader = getClassLoader();
Map<ClassLoader, ClassLoaderData> cache = CACHE;
// 根据类加载器获取缓存
ClassLoaderData data = cache.get(loader);
if (data == null) {
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;
// getUseCache()默认为true,用于设值是否启用缓存
Object obj = data.get(this, getUseCache());
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);
}
}
// 省略部分代码
}
AbstractClassGenerator.create(key)
流程大致如下:
- 通过类加载器从
CACHE
中获取对应缓存,若根据类加载器未获取到缓存,则初始化后放入缓存;// AbstractClassGenerator.create()部分代码片段 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; }
ClassLoaderData
是AbstractClassGenerator
的内部类,通过data.get(this, getUseCache())
从缓存获取Class实例或通过asm生成字节码文件返回Class实例。
最后一步很关键data.get(this, getUseCache())
,源码如下:
// AbstractClassGenerator内部类ClassLoaderData源码
protected static class ClassLoaderData {
// 部分代码省略
private final LoadingCache<AbstractClassGenerator, Object, Object> generatedClasses;
private final WeakReference<ClassLoader> classLoader;
// 部分代码省略
private static final Function<AbstractClassGenerator, Object> GET_KEY = new Function<AbstractClassGenerator, Object>() {
public Object apply(AbstractClassGenerator gen) {
return gen.key;
}
};
public ClassLoaderData(ClassLoader classLoader) {
if (classLoader == null) {
throw new IllegalArgumentException("classLoader == null is not yet supported");
}
this.classLoader = new WeakReference<ClassLoader>(classLoader);
Function<AbstractClassGenerator, Object> load =
new Function<AbstractClassGenerator, Object>() {
public Object apply(AbstractClassGenerator gen) {
// 生成字节码文件,载入并初始化返回Class实例
Class klass = gen.generate(ClassLoaderData.this);
return gen.wrapCachedClass(klass);
}
};
generatedClasses = new LoadingCache<AbstractClassGenerator, Object, Object>(GET_KEY, load);
}
public Object get(AbstractClassGenerator gen, boolean useCache) {
// 判断是否通过缓存获取
if (!useCache) {
return gen.generate(ClassLoaderData.this);
} else {
Object cachedValue = generatedClasses.get(gen);
return gen.unwrapCachedValue(cachedValue);
}
}
}
data.get(this, getUseCache())
大致流程如下:
-
useCache=true
则generatedClasses.get(gen)
从缓存获取,若缓存不存在则通过gen.generate()
创建Class实例后放入缓存。// net.sf.cglib.core.internal.LoadingCache部分源码 public class LoadingCache<K, KK, V> { protected final ConcurrentMap<KK, Object> map; protected final Function<K, V> loader; protected final Function<K, KK> keyMapper; // 部分省略 // V : 代理类的Class // KK : 生成Key的类 // K : AbstractClassGenerator public V get(K key) { // 生成cacheKey并从ConcurrentMap<KK, Object> map中获取代理类的Class final KK cacheKey = keyMapper.apply(key); Object v = map.get(cacheKey); if (v != null && !(v instanceof FutureTask)) { return (V) v; } // 未获取到则创建Class并放入缓存 return createEntry(key, cacheKey, v); } protected V createEntry(final K key, KK cacheKey, Object v) { FutureTask<V> task; boolean creator = false; // 代码部分省略 task = new FutureTask<V>(new Callable<V>() { public V call() throws Exception { // 生成class return loader.apply(key); } }); Object prevTask = map.putIfAbsent(cacheKey, task); if (prevTask == null) { creator = true; task.run(); } else if (prevTask instanceof FutureTask) { task = (FutureTask<V>) prevTask; } else { return (V) prevTask; } V result = task.get(); // 代码部分省略 if (creator) { // 放入缓存 map.put(cacheKey, result); } return result; } }
// loader.apply(key)的实现是在ClassLoaderData构造方法中 public Object apply(AbstractClassGenerator gen) { Class klass = gen.generate(ClassLoaderData.this); return gen.wrapCachedClass(klass); }
-
否则直接
gen.generate(ClassLoaderData.this)
生成字节码文件,载入并初始化返回Class实例。
OK,继续跟进gen.generate(ClassLoaderData.this)
这块的代码逻辑:
// AbstractClassGenerator部分代码片段
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);
}
// 通过类加载器尝试加载getClassName(),加载不到抛出异常继续向下执行
if (attemptLoad) {
try {
// ClassLoader.loadClass(classname,false):将字节码文件加载到JVM中,false:标识不进行连接,即不会被初始化,默认false
// Class.forName(className,true,classloader):除了将字节码文件加载到JVM中,true标识:自动初始化,默认为true
gen = classLoader.loadClass(getClassName());
return gen;
} catch (ClassNotFoundException e) {
// ignore
}
}
// 生成字节码数组
byte[] b = strategy.generate(this);
String className = ClassNameReader.getClassName(new ClassReader(b));
ProtectionDomain protectionDomain = getProtectionDomain();
synchronized (classLoader) { // just in case
// 将上面生成的字节码加载到内存返回Class实例
// Class.forName(className, true, loader);
if (protectionDomain == null) {
gen = ReflectUtils.defineClass(className, b, classLoader);
} else {
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);
}
}
大致流程如下:
- 生成类名称,生成规则:类全限定名+来源+16进制的hash值:
// net.sf.cglib.core.DefaultNamingPolicy 部分代码片段 public String getClassName(String prefix, String source, Object key, Predicate names) { if (prefix == null) { 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; }
- 通过类加载器尝试加载上面生成的类名称,成功就返回,失败则继续执行。
- 通过asm框架工具类DefaultGeneratorStrategy生成字节码数组(涉及的内容较多,本文不展开阅读),通过Class.forName()转换为Class。
// net.sf.cglib.core.ReflectUtils部分源码 public static Class defineClass(String className, byte[] b, ClassLoader loader, ProtectionDomain protectionDomain) throws Exception { Class c; if (DEFINE_CLASS != null) { Object[] args = new Object[]{className, b, new Integer(0), new Integer(b.length), protectionDomain }; c = (Class)DEFINE_CLASS.invoke(loader, args); } else if (DEFINE_CLASS_UNSAFE != null) { Object[] args = new Object[]{className, b, new Integer(0), new Integer(b.length), loader, protectionDomain }; c = (Class)DEFINE_CLASS_UNSAFE.invoke(UNSAFE, args); } else { throw new CodeGenerationException(THROWABLE); } // Force static initializers to run. Class.forName(className, true, loader); return c; }
至此CGLib生成代理类的流程我们通过以上源码都大致了解了,那么它的调用过程呢?
1.2.2 CGLib通过什么方式调用代理类的方法呢?
在代码示例中我们通过配置DEBUG_LOCATION_PROPERTY
的值来保存CGLib生成的文件,查看对应路径下的文件如下:
// System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "输出路径")
// 1.代理类的FastClass类
Bank$$EnhancerByCGLIB$$406a1aa1$$FastClassByCGLIB$$7a777fd6.class
// 2.代理类
Bank$$EnhancerByCGLIB$$406a1aa1.class
// 3.被代理的FastClass类
Bank$$FastClassByCGLIB$$75312cb7.class
接下来我们先查看生成的代理类源码(我是通过IDEA打开,可以自行选择):
public class Bank$$EnhancerByCGLIB$$406a1aa1 extends Bank 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;
// 通过enhancer.setCallback设置的对应拦截器
private MethodInterceptor CGLIB$CALLBACK_0;
private static Object CGLIB$CALLBACK_FILTER;
// 代理类方法 每个方法对应一个Method 及 MethodProxy
private static final Method CGLIB$transfer$0$Method;
private static final MethodProxy CGLIB$transfer$0$Proxy;
private static final Object[] CGLIB$emptyArgs;
private static final Method CGLIB$withdraw$1$Method;
private static final MethodProxy CGLIB$withdraw$1$Proxy;
private static final Method CGLIB$equals$2$Method;
private static final MethodProxy CGLIB$equals$2$Proxy;
private static final Method CGLIB$toString$3$Method;
private static final MethodProxy CGLIB$toString$3$Proxy;
private static final Method CGLIB$hashCode$4$Method;
private static final MethodProxy CGLIB$hashCode$4$Proxy;
private static final Method CGLIB$clone$5$Method;
private static final MethodProxy CGLIB$clone$5$Proxy;
// 初始化
static void CGLIB$STATICHOOK1() {
CGLIB$THREAD_CALLBACKS = new ThreadLocal();
CGLIB$emptyArgs = new Object[0];
Class var0 = Class.forName("demo6.Bank$$EnhancerByCGLIB$$406a1aa1");
Class var1;
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$2$Method = var10000[0];
CGLIB$equals$2$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$2");
CGLIB$toString$3$Method = var10000[1];
CGLIB$toString$3$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/String;", "toString", "CGLIB$toString$3");
CGLIB$hashCode$4$Method = var10000[2];
CGLIB$hashCode$4$Proxy = MethodProxy.create(var1, var0, "()I", "hashCode", "CGLIB$hashCode$4");
CGLIB$clone$5$Method = var10000[3];
CGLIB$clone$5$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/Object;", "clone", "CGLIB$clone$5");
// 获取父类的方法
var10000 = ReflectUtils.findMethods(new String[]{"transfer", "(Ljava/lang/String;)V", "withdraw", "(Ljava/lang/String;)V"}, (var1 = Class.forName("demo6.Bank")).getDeclaredMethods());
CGLIB$transfer$0$Method = var10000[0];
CGLIB$transfer$0$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/String;)V", "transfer", "CGLIB$transfer$0");
CGLIB$withdraw$1$Method = var10000[1];
CGLIB$withdraw$1$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/String;)V", "withdraw", "CGLIB$withdraw$1");
}
// 直接调用父类方法
final void CGLIB$transfer$0(String var1) {
super.transfer(var1);
}
// 设置了拦截器则调用对应拦截器的intercept()方法
public final void transfer(String var1) {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
if (var10000 != null) {
var10000.intercept(this, CGLIB$transfer$0$Method, new Object[]{var1}, CGLIB$transfer$0$Proxy);
} else {
super.transfer(var1);
}
}
// 如上类似
final void CGLIB$withdraw$1(String var1) {
super.withdraw(var1);
}
// 如上类似
public final void withdraw(String var1) {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
if (var10000 != null) {
var10000.intercept(this, CGLIB$withdraw$1$Method, new Object[]{var1}, CGLIB$withdraw$1$Proxy);
} else {
super.withdraw(var1);
}
}
// 省略clone() toString() hashCode() equals() 部分源码
public static MethodProxy CGLIB$findMethodProxy(Signature var0) {
String var10000 = var0.toString();
switch(var10000.hashCode()) {
case -566439627:
if (var10000.equals("withdraw(Ljava/lang/String;)V")) {
return CGLIB$withdraw$1$Proxy;
}
break;
// 部分省略···
case 447064820:
if (var10000.equals("transfer(Ljava/lang/String;)V")) {
return CGLIB$transfer$0$Proxy;
}
break;
// 部分省略···
}
return null;
}
public Bank$$EnhancerByCGLIB$$406a1aa1() {
CGLIB$BIND_CALLBACKS(this);
}
public static void CGLIB$SET_STATIC_CALLBACKS(Callback[] var0) {
CGLIB$STATIC_CALLBACKS = var0;
}
private static final void CGLIB$BIND_CALLBACKS(Object var0) {
Bank$$EnhancerByCGLIB$$406a1aa1 var1 = (Bank$$EnhancerByCGLIB$$406a1aa1)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];
}
}
// 部分省略···
static {
CGLIB$STATICHOOK1();
}
}
回顾一下我们的示例代码:
- demo示例中,我们通过
enhancer.create()
获得代理类实例Bank$$EnhancerByCGLIB$$406a1aa1
(如上源码),在初始化的过程中会为每个方法生成对应的Method与MethodProxy。static { CGLIB$STATICHOOK1(); }
- 接下来调用
transfer()
方法时判断是否设置拦截器,在设置拦截器的情况下判断分支会执行到var10000.intercept();
// Bank$$EnhancerByCGLIB$$406a1aa1 部分源码 public final void transfer(String var1) { // 指定的拦截器否则非null MethodInterceptor var10000 = this.CGLIB$CALLBACK_0; if (var10000 == null) { CGLIB$BIND_CALLBACKS(this); var10000 = this.CGLIB$CALLBACK_0; } if (var10000 != null) { // 参数释义分别是:代理类、拦截的方法、参数、方法代理 var10000.intercept(this, CGLIB$transfer$0$Method, new Object[]{var1}, CGLIB$transfer$0$Proxy); } else { super.transfer(var1); } }
- 然后调用拦截器ATM.intercept()方法,打印
开始业务操作···
public class ATM implements MethodInterceptor { /** * @param o 增强的对象 * @param method 拦截的方法 * @param objects 参数数组 * @param methodProxy 对方法的代理 * @return o */ @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { operation(false); methodProxy.invokeSuper(o, objects); operation(true); return o; } private void operation(boolean finishFlag) { String currentStatus = finishFlag ? "业务处理完毕,收起银行卡。" : "开始业务操作···"; System.out.println(currentStatus); } }
- 然后通过
methodProxy.invokeSuper(o, objects)
调用父类方法。
methodProxy.invokeSuper(o, objects)
如何调用父类方法呢?
// et.sf.cglib.proxy.MethodProxy
public class MethodProxy {
// 方法签名
private Signature sig1;
private Signature sig2;
private CreateInfo createInfo;
private final Object initLock = new Object();
private volatile FastClassInfo fastClassInfo;
/**
* @param c1 被代理对象
* @param c2 代理对象
* @param desc 参数描述
* @param name1 被代理方法
* @param name2 代理方法
*/
public static MethodProxy create(Class c1, Class c2, String desc, String name1, String name2) {
MethodProxy proxy = new MethodProxy();
proxy.sig1 = new Signature(name1, desc);
proxy.sig2 = new Signature(name2, desc);
proxy.createInfo = new CreateInfo(c1, c2);
return proxy;
}
private static class FastClassInfo {
// 被代理对象FastClass
FastClass f1;
// 代理对象FastClass
FastClass f2;
// 被代理对象方法索引
int i1;
// 代理对象方法索引
int i2;
}
private static class CreateInfo {
Class c1;
Class c2;
NamingPolicy namingPolicy;
GeneratorStrategy strategy;
boolean attemptLoad;
public CreateInfo(Class c1, Class c2) {
this.c1 = c1;
this.c2 = c2;
AbstractClassGenerator fromEnhancer = AbstractClassGenerator.getCurrent();
if (fromEnhancer != null) {
namingPolicy = fromEnhancer.getNamingPolicy();
strategy = fromEnhancer.getStrategy();
attemptLoad = fromEnhancer.getAttemptLoad();
}
}
}
// 部分代码省略
// 被代理类FastClass通过被代理对象方法索引调用代理类方法
public Object invoke(Object obj, Object[] args) throws Throwable {
try {
init();
FastClassInfo fci = fastClassInfo;
return fci.f1.invoke(fci.i1, obj, args);
} catch (InvocationTargetException e) {
throw e.getTargetException();
} catch (IllegalArgumentException e) {
if (fastClassInfo.i1 < 0)
throw new IllegalArgumentException("Protected method: " + sig1);
throw e;
}
}
/**
* 代理类FastClass通过代理对象方法索引,实际调用代理类父类方法
*
* @param obj 代理类
* @param args 参数数组
*/
public Object invokeSuper(Object obj, Object[] args) throws Throwable {
try {
// 初始化
init();
FastClassInfo fci = fastClassInfo;
// 调用代理对象FastClass.invoke方法(也就是我们上面看到的生成文件Bank$$EnhancerByCGLIB$$406a1aa1$$FastClassByCGLIB$$7a777fd6对象)
return fci.f2.invoke(fci.i2, obj, args);
} catch (InvocationTargetException e) {
throw e.getTargetException();
}
}
// 创建被代理对象FastClass(f1)、代理对象fastClass(f2)、被代理对象方法(i1)、代理对象方法(i2)
private void init() {
if (fastClassInfo == null) {
synchronized (initLock) {
if (fastClassInfo == null) {
CreateInfo ci = createInfo;
FastClassInfo fci = new FastClassInfo();
fci.f1 = helper(ci, ci.c1);
fci.f2 = helper(ci, ci.c2);
fci.i1 = fci.f1.getIndex(sig1);
fci.i2 = fci.f2.getIndex(sig2);
fastClassInfo = fci;
createInfo = null;
}
}
}
}
}
methodProxy.invokeSuper(o, objects)
大致流程如下:
init()
创建被代理对象FastClass与代理对象fastClass、获取被代理对象方法索引与代理对象方法索引- 通过
ci.f2.invoke(fci.i2, obj, args)
,代理类FastClass通过代理对象方法索引,调用代理类父类方法。
打开生成的代理类FastClass部分源码如下:
public class Bank$$EnhancerByCGLIB$$406a1aa1$$FastClassByCGLIB$$7a777fd6 extends FastClass {
public Bank$$EnhancerByCGLIB$$406a1aa1$$FastClassByCGLIB$$7a777fd6(Class var1) {
super(var1);
}
public int getIndex(Signature var1) {
String var10000 = var1.toString();
switch(var10000.hashCode()) {
// 省略
case -566439627:
if (var10000.equals("withdraw(Ljava/lang/String;)V")) {
return 9;
}
break;
case 123475845:
if (var10000.equals("CGLIB$transfer$0(Ljava/lang/String;)V")) {
return 20;
}
break;
// 省略
}
return -1;
}
public int getIndex(String var1, Class[] var2) {
switch(var1.hashCode()) {
case -1958972742:
if (var1.equals("CGLIB$transfer$0")) {
switch(var2.length) {
case 1:
if (var2[0].getName().equals("java.lang.String")) {
return 20;
}
}
}
break;
case -1861191142:
if (var1.equals("CGLIB$withdraw$1")) {
switch(var2.length) {
case 1:
if (var2[0].getName().equals("java.lang.String")) {
return 18;
}
}
}
break;
// 省略
}
return -1;
}
public int getIndex(Class[] var1) {
switch(var1.length) {
case 0:
return 0;
default:
return -1;
}
}
/**
* @var1 方法索引
* @var2 代理类
* @var3 参数
*/
public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {
406a1aa1 var10000 = (406a1aa1)var2;
int var10001 = var1;
try {
switch(var10001) {
case 18:
var10000.CGLIB$withdraw$1((String)var3[0]);
return null;
case 20:
var10000.CGLIB$transfer$0((String)var3[0]);
} catch (Throwable var4) {
throw new InvocationTargetException(var4);
}
throw new IllegalArgumentException("Cannot find matching method/constructor");
}
// 省略
}
通过以上代理类FastClass源码我们可以看到,在调用时通过方法索引找到对应方法,然后调用代理类的CGLIB$transfer$0((String)var3[0])
方法完成最终调用。调用完毕最终输出“业务处理完毕,收起银行卡”,至此整个流程结束。
// Bank$$EnhancerByCGLIB$$406a1aa1代理类部分源码
// 直接调用父类方法
final void CGLIB$transfer$0(String var1) {
super.transfer(var1);
}
学而思
将代码示例中ATM的methodProxy.invokeSuper()
修改为methodProxy.invoke()
将会导致StackOverflowError
,这是什么原因呢?有兴趣的同学可以自行研究一下,找到对应的解决方式。
总结
通过源码阅读的方式,我们了解了代理类生成的生成逻辑与最终如何调用被代理类目标方法的逻辑,形成了对CGLib从模糊到清晰的印象。