//此方法也是Proxy类下的方法
private static Class> getProxyClass0(ClassLoader loader,
Class>... interfaces) {
if (interfaces.length > 65535) {
throw new IllegalArgumentException("interface limit exceeded");
}
// If the proxy class defined by the given loader implementing
// the given interfaces exists, this will simply return the cached copy;
// otherwise, it will create the proxy class via the ProxyClassFactory
//意思是:如果代理类被指定的类加载器loader定义了,并实现了给定的接口interfaces,
//那么就返回缓存的代理类对象,否则使用ProxyClassFactory创建代理类。
return proxyClassCache.get(loader, interfaces);
}
这里看到proxyClassCache,有Cache便知道是缓存的意思,正好呼应了前面Look up or generate the designated proxy class。查询(在缓存中已经有)或生成指定的代理类的class对象这段注释。
//K代表key的类型,P代表参数的类型,V代表value的类型。
// WeakCache[], Class>> proxyClassCache 说明proxyClassCache存的值是Class>对象,正是我们需要的代理类对象。
final class WeakCache {
private final ReferenceQueue refQueue
= new ReferenceQueue();
// the key type is Object for supporting null key
private final ConcurrentMap
//K和P就是WeakCache定义中的泛型,key是类加载器,parameter是接口类数组
public V get(K key, P parameter) {
//检查parameter不为空
Objects.requireNonNull(parameter);
//清除无效的缓存
expungeStaleEntries();
// cacheKey就是(key, sub-key) -> value里的一级key,
Object cacheKey = CacheKey.valueOf(key, refQueue);
// lazily install the 2nd level valuesMap for the particular cacheKey
//根据一级key得到 ConcurrentMap
所以接下来我们看Factory类中的get方法。
public synchronized V get() { // serialize access
// re-check
Supplier supplier = valuesMap.get(subKey);
//重新检查得到的supplier是不是当前对象
if (supplier != this) {
// something changed while we were waiting:
// might be that we were replaced by a CacheValue
// or were removed because of failure ->
// return null to signal WeakCache.get() to retry
// the loop
return null;
}
// else still us (supplier == this)
// create new value
V value = null;
try {
//代理类就是在这个位置调用valueFactory生成的
//valueFactory就是我们传入的 new ProxyClassFactory()
//一会我们分析ProxyClassFactory()的apply方法
value = Objects.requireNonNull(valueFactory.apply(key, parameter));
} finally {
if (value == null) { // remove us on failure
valuesMap.remove(subKey, this);
}
}
// the only path to reach here is with non-null value
assert value != null;
// wrap value with CacheValue (WeakReference)
//把value包装成弱引用
CacheValue cacheValue = new CacheValue(value);
// put into reverseMap
// reverseMap是用来实现缓存的有效性
reverseMap.put(cacheValue, Boolean.TRUE);
// try replacing us with CacheValue (this should always succeed)
if (!valuesMap.replace(subKey, this, cacheValue)) {
throw new AssertionError("Should not reach here");
}
// successfully replaced us with new CacheValue -> return the value
// wrapped by it
return value;
}
}
拨云见日,来到ProxyClassFactory的apply方法,代理类就是在这里生成的。
//这里的BiFunction是个函数式接口,可以理解为用T,U两种类型做参数,得到R类型的返回值
private static final class ProxyClassFactory
implements BiFunction[], Class>>
{
// prefix for all proxy class names
//所有代理类名字的前缀
private static final String proxyClassNamePrefix = "$Proxy";
// next number to use for generation of unique proxy class names
//用于生成代理类名字的计数器
private static final AtomicLong nextUniqueNumber = new AtomicLong();
@Override
public Class> apply(ClassLoader loader, Class>[] interfaces) {
Map, Boolean> interfaceSet = new IdentityHashMap(interfaces.length);
//验证代理接口,可不看
for (Class> intf : interfaces) {
/*
* Verify that the class loader resolves the name of this
* interface to the same Class object.
*/
Class> interfaceClass = null;
try {
interfaceClass = Class.forName(intf.getName(), false, loader);
} catch (ClassNotFoundException e) {
}
if (interfaceClass != intf) {
throw new IllegalArgumentException(
intf + " is not visible from class loader");
}
/*
* Verify that the Class object actually represents an
* interface.
*/
if (!interfaceClass.isInterface()) {
throw new IllegalArgumentException(
interfaceClass.getName() + " is not an interface");
}
/*
* Verify that this interface is not a duplicate.
*/
if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {
throw new IllegalArgumentException(
"repeated interface: " + interfaceClass.getName());
}
}
//生成的代理类的包名
String proxyPkg = null; // package to define proxy class in
//代理类访问控制符: public ,final
int accessFlags = Modifier.PUBLIC | Modifier.FINAL;
/*
* Record the package of a non-public proxy interface so that the
* proxy class will be defined in the same package. Verify that
* all non-public proxy interfaces are in the same package.
*/
//验证所有非公共的接口在同一个包内;公共的就无需处理
//生成包名和类名的逻辑,包名默认是com.sun.proxy,类名默认是$Proxy 加上一个自增的整数值
//如果被代理类是 non-public proxy interface ,则用和被代理类接口一样的包名
for (Class> intf : interfaces) {
int flags = intf.getModifiers();
if (!Modifier.isPublic(flags)) {
accessFlags = Modifier.FINAL;
String name = intf.getName();
int n = name.lastIndexOf('.');
String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
if (proxyPkg == null) {
proxyPkg = pkg;
} else if (!pkg.equals(proxyPkg)) {
throw new IllegalArgumentException(
"non-public interfaces from different packages");
}
}
}
if (proxyPkg == null) {
// if no non-public proxy interfaces, use com.sun.proxy package
proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
}
/*
* Choose a name for the proxy class to generate.
*/
long num = nextUniqueNumber.getAndIncrement();
//代理类的完全限定名,如com.sun.proxy.$Proxy0.calss
String proxyName = proxyPkg + proxyClassNamePrefix + num;
/*
* Generate the specified proxy class.
*/
//核心部分,生成代理类的字节码
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces, accessFlags);
try {
//把代理类加载到JVM中,至此动态代理过程基本结束了
return defineClass0(loader, proxyName,
proxyClassFile, 0, proxyClassFile.length);
} catch (ClassFormatError e) {
/*
* A ClassFormatError here means that (barring bugs in the
* proxy class generation code) there was some other
* invalid aspect of the arguments supplied to the proxy
* class creation (such as virtual machine limitations
* exceeded).
*/
throw new IllegalArgumentException(e.toString());
}
}
}
void expungeFrom(ConcurrentMap, ? extends ConcurrentMap, ?>> map,
ConcurrentMap, Boolean> reverseMap) {
// removing just by key is always safe here because after a CacheKey
// is cleared and enqueue-ed it is only equal to itself
// (see equals method)...
ConcurrentMap, ?> valuesMap = map.remove(this);
// remove also from reverseMap if needed
if (valuesMap != null) {
for (Object cacheValue : valuesMap.values()) {
reverseMap.remove(cacheValue);
}
}
}
private static final class CacheKey extends WeakReference {
// a replacement for null keys
private static final Object NULL_KEY = new Object();
static Object valueOf(K key, ReferenceQueue refQueue) {
return key == null
// null key means we can't weakly reference it,
// so we use a NULL_KEY singleton as cache key
? NULL_KEY
// non-null key requires wrapping with a WeakReference
: new CacheKey(key, refQueue);
}
private final int hash;
private CacheKey(K key, ReferenceQueue refQueue) {
super(key, refQueue);
this.hash = System.identityHashCode(key); // compare by identity
}
.....
}
public ClassLoaderData(ClassLoader classLoader) {
if (classLoader == null) {
throw new IllegalArgumentException("classLoader == null is not yet supported");
}
this.classLoader = new WeakReference(classLoader);
Function load =
new Function() {
public Object apply(AbstractClassGenerator gen) {
Class klass = gen.generate(ClassLoaderData.this);
return gen.wrapCachedClass(klass);
}
};
generatedClasses = new LoadingCache(GET_KEY, load);
}
public ClassLoader getClassLoader() { return classLoader.get(); }
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.");
}
/**
* Whether use and update the static cache of generated classes
* for a class with the same properties. Default is true.
*/
public void setUseCache(boolean useCache) {
this.useCache = useCache;
}
/**
* @see #setUseCache
*/
public boolean getUseCache() {
return useCache;
}
public V get(K key) {
final KK cacheKey = keyMapper.apply(key);
Object v = map.get(cacheKey);
if (v != null && !(v instanceof FutureTask)) {
return (V) v;
}
return createEntry(key, cacheKey, v);
}
privatevoid emitMethods(final ClassEmitter ce, List methods, List actualMethods) {
...........
MethodInfo method = (MethodInfo)it1.next();
Method actualMethod = (it2 != null) ? (Method)it2.next() : null;
int index = filter.accept(actualMethod);
if (index >= callbackTypes.length) {
thrownew IllegalArgumentException("Callback filter returned an index that is too large: " + index);
}
originalModifiers.put(method, new Integer((actualMethod != null) ? actualMethod.getModifiers() : method.getModifiers()));
indexes.put(method, new Integer(index));
List group = (List)groups.get(generators[index]);
if (group == null) {
groups.put(generators[index], group = new ArrayList(methods.size()));
}
group.add(method);
................
}
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package cglib;
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;
public class CglibTest$$EnhancerByCGLIB$$fc037646 extends CglibTest 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;
private static final Method CGLIB$hello$0$Method;
private static final MethodProxy CGLIB$hello$0$Proxy;
private static final Object[] CGLIB$emptyArgs;
private static final Method CGLIB$intercept$1$Method;
private static final MethodProxy CGLIB$intercept$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("cglib.CglibTest$$EnhancerByCGLIB$$fc037646");
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[]{"hello", "(Ljava/lang/String;)Ljava/lang/String;", "intercept", "(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;Lnet/sf/cglib/proxy/MethodProxy;)Ljava/lang/Object;"}, (var1 = Class.forName("cglib.CglibTest")).getDeclaredMethods());
CGLIB$hello$0$Method = var10000[0];
CGLIB$hello$0$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/String;)Ljava/lang/String;", "hello", "CGLIB$hello$0");
CGLIB$intercept$1$Method = var10000[1];
CGLIB$intercept$1$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;Lnet/sf/cglib/proxy/MethodProxy;)Ljava/lang/Object;", "intercept", "CGLIB$intercept$1");
}
final String CGLIB$hello$0(String var1) {
return super.hello(var1);
}
public final String hello(String var1) {
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$hello$0$Method, new Object[]{var1}, CGLIB$hello$0$Proxy) : super.hello(var1);
}
final Object CGLIB$intercept$1(Object var1, Method var2, Object[] var3, MethodProxy var4) throws Throwable {
return super.intercept(var1, var2, var3, var4);
}
public final Object intercept(Object var1, Method var2, Object[] var3, MethodProxy var4) throws Throwable {
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$intercept$1$Method, new Object[]{var1, var2, var3, var4}, CGLIB$intercept$1$Proxy) : super.intercept(var1, var2, var3, var4);
}
final boolean CGLIB$equals$2(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$2$Method, new Object[]{var1}, CGLIB$equals$2$Proxy);
return var2 == null ? false : (Boolean)var2;
} else {
return super.equals(var1);
}
}
final String CGLIB$toString$3() {
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$3$Method, CGLIB$emptyArgs, CGLIB$toString$3$Proxy) : super.toString();
}
final int CGLIB$hashCode$4() {
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$4$Method, CGLIB$emptyArgs, CGLIB$hashCode$4$Proxy);
return var1 == null ? 0 : ((Number)var1).intValue();
} else {
return super.hashCode();
}
}
final Object CGLIB$clone$5() 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$5$Method, CGLIB$emptyArgs, CGLIB$clone$5$Proxy) : super.clone();
}
public static MethodProxy CGLIB$findMethodProxy(Signature var0) {
String var10000 = var0.toString();
switch(var10000.hashCode()) {
case -1249666147:
if (var10000.equals("intercept(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;Lnet/sf/cglib/proxy/MethodProxy;)Ljava/lang/Object;")) {
return CGLIB$intercept$1$Proxy;
}
break;
case -508378822:
if (var10000.equals("clone()Ljava/lang/Object;")) {
return CGLIB$clone$5$Proxy;
}
break;
case 848333779:
if (var10000.equals("hello(Ljava/lang/String;)Ljava/lang/String;")) {
return CGLIB$hello$0$Proxy;
}
break;
case 1826985398:
if (var10000.equals("equals(Ljava/lang/Object;)Z")) {
return CGLIB$equals$2$Proxy;
}
break;
case 1913648695:
if (var10000.equals("toString()Ljava/lang/String;")) {
return CGLIB$toString$3$Proxy;
}
break;
case 1984935277:
if (var10000.equals("hashCode()I")) {
return CGLIB$hashCode$4$Proxy;
}
}
return null;
}
public CglibTest$$EnhancerByCGLIB$$fc037646() {
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) {
CglibTest$$EnhancerByCGLIB$$fc037646 var1 = (CglibTest$$EnhancerByCGLIB$$fc037646)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);
CglibTest$$EnhancerByCGLIB$$fc037646 var10000 = new CglibTest$$EnhancerByCGLIB$$fc037646();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
}
public Object newInstance(Callback var1) {
CGLIB$SET_THREAD_CALLBACKS(new Callback[]{var1});
CglibTest$$EnhancerByCGLIB$$fc037646 var10000 = new CglibTest$$EnhancerByCGLIB$$fc037646();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
}
public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) {
CGLIB$SET_THREAD_CALLBACKS(var3);
CglibTest$$EnhancerByCGLIB$$fc037646 var10000 = new CglibTest$$EnhancerByCGLIB$$fc037646;
switch(var1.length) {
case 0:
var10000.();
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();
}
}
代理类的FastClass
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package cglib;
import cglib.CglibTest..EnhancerByCGLIB..fc037646;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import net.sf.cglib.core.Signature;
import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.MethodProxy;
import net.sf.cglib.reflect.FastClass;
public class CglibTest$$EnhancerByCGLIB$$fc037646$$FastClassByCGLIB$$ec49b181 extends FastClass {
public CglibTest$$EnhancerByCGLIB$$fc037646$$FastClassByCGLIB$$ec49b181(Class var1) {
super(var1);
}
public int getIndex(Signature var1) {
String var10000 = var1.toString();
switch(var10000.hashCode()) {
case -2055565910:
if (var10000.equals("CGLIB$SET_THREAD_CALLBACKS([Lnet/sf/cglib/proxy/Callback;)V")) {
return 3;
}
break;
case -1457535688:
if (var10000.equals("CGLIB$STATICHOOK1()V")) {
return 16;
}
break;
case -1411812934:
if (var10000.equals("CGLIB$hashCode$4()I")) {
return 21;
}
break;
case -1249666147:
if (var10000.equals("intercept(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;Lnet/sf/cglib/proxy/MethodProxy;)Ljava/lang/Object;")) {
return 14;
}
break;
case -894172689:
if (var10000.equals("newInstance(Lnet/sf/cglib/proxy/Callback;)Ljava/lang/Object;")) {
return 11;
}
break;
case -879968516:
if (var10000.equals("CGLIB$hello$0(Ljava/lang/String;)Ljava/lang/String;")) {
return 17;
}
break;
case -623122092:
if (var10000.equals("CGLIB$findMethodProxy(Lnet/sf/cglib/core/Signature;)Lnet/sf/cglib/proxy/MethodProxy;")) {
return 0;
}
break;
case -508378822:
if (var10000.equals("clone()Ljava/lang/Object;")) {
return 9;
}
break;
case -419626537:
if (var10000.equals("setCallbacks([Lnet/sf/cglib/proxy/Callback;)V")) {
return 1;
}
break;
case 374345669:
if (var10000.equals("CGLIB$equals$2(Ljava/lang/Object;)Z")) {
return 19;
}
break;
case 560567118:
if (var10000.equals("setCallback(ILnet/sf/cglib/proxy/Callback;)V")) {
return 15;
}
break;
case 811063227:
if (var10000.equals("newInstance([Ljava/lang/Class;[Ljava/lang/Object;[Lnet/sf/cglib/proxy/Callback;)Ljava/lang/Object;")) {
return 12;
}
break;
case 848333779:
if (var10000.equals("hello(Ljava/lang/String;)Ljava/lang/String;")) {
return 13;
}
break;
case 973717575:
if (var10000.equals("getCallbacks()[Lnet/sf/cglib/proxy/Callback;")) {
return 5;
}
break;
case 1115619315:
if (var10000.equals("CGLIB$intercept$1(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;Lnet/sf/cglib/proxy/MethodProxy;)Ljava/lang/Object;")) {
return 18;
}
break;
case 1221173700:
if (var10000.equals("newInstance([Lnet/sf/cglib/proxy/Callback;)Ljava/lang/Object;")) {
return 10;
}
break;
case 1230699260:
if (var10000.equals("getCallback(I)Lnet/sf/cglib/proxy/Callback;")) {
return 4;
}
break;
case 1341835395:
if (var10000.equals("main([Ljava/lang/String;)V")) {
return 23;
}
break;
case 1517819849:
if (var10000.equals("CGLIB$toString$3()Ljava/lang/String;")) {
return 20;
}
break;
case 1584330438:
if (var10000.equals("CGLIB$SET_STATIC_CALLBACKS([Lnet/sf/cglib/proxy/Callback;)V")) {
return 2;
}
break;
case 1826985398:
if (var10000.equals("equals(Ljava/lang/Object;)Z")) {
return 6;
}
break;
case 1913648695:
if (var10000.equals("toString()Ljava/lang/String;")) {
return 7;
}
break;
case 1984935277:
if (var10000.equals("hashCode()I")) {
return 8;
}
break;
case 2011844968:
if (var10000.equals("CGLIB$clone$5()Ljava/lang/Object;")) {
return 22;
}
}
return -1;
}
public int getIndex(String var1, Class[] var2) {
switch(var1.hashCode()) {
case -1776922004:
if (var1.equals("toString")) {
switch(var2.length) {
case 0:
return 7;
}
}
break;
case -1295482945:
if (var1.equals("equals")) {
switch(var2.length) {
case 1:
if (var2[0].getName().equals("java.lang.Object")) {
return 6;
}
}
}
break;
case -1053468136:
if (var1.equals("getCallbacks")) {
switch(var2.length) {
case 0:
return 5;
}
}
break;
case -981624788:
if (var1.equals("CGLIB$intercept$1")) {
switch(var2.length) {
case 4:
if (var2[0].getName().equals("java.lang.Object") && var2[1].getName().equals("java.lang.reflect.Method") && var2[2].getName().equals("[Ljava.lang.Object;") && var2[3].getName().equals("net.sf.cglib.proxy.MethodProxy")) {
return 18;
}
}
}
break;
case -124978608:
if (var1.equals("CGLIB$equals$2")) {
switch(var2.length) {
case 1:
if (var2[0].getName().equals("java.lang.Object")) {
return 19;
}
}
}
break;
case -60403779:
if (var1.equals("CGLIB$SET_STATIC_CALLBACKS")) {
switch(var2.length) {
case 1:
if (var2[0].getName().equals("[Lnet.sf.cglib.proxy.Callback;")) {
return 2;
}
}
}
break;
case -29025554:
if (var1.equals("CGLIB$hashCode$4")) {
switch(var2.length) {
case 0:
return 21;
}
}
break;
case 3343801:
if (var1.equals("main")) {
switch(var2.length) {
case 1:
if (var2[0].getName().equals("[Ljava.lang.String;")) {
return 23;
}
}
}
break;
case 85179481:
if (var1.equals("CGLIB$SET_THREAD_CALLBACKS")) {
switch(var2.length) {
case 1:
if (var2[0].getName().equals("[Lnet.sf.cglib.proxy.Callback;")) {
return 3;
}
}
}
break;
case 94756189:
if (var1.equals("clone")) {
switch(var2.length) {
case 0:
return 9;
}
}
break;
case 99162322:
if (var1.equals("hello")) {
switch(var2.length) {
case 1:
if (var2[0].getName().equals("java.lang.String")) {
return 13;
}
}
}
break;
case 147696667:
if (var1.equals("hashCode")) {
switch(var2.length) {
case 0:
return 8;
}
}
break;
case 161998109:
if (var1.equals("CGLIB$STATICHOOK1")) {
switch(var2.length) {
case 0:
return 16;
}
}
break;
case 495524492:
if (var1.equals("setCallbacks")) {
switch(var2.length) {
case 1:
if (var2[0].getName().equals("[Lnet.sf.cglib.proxy.Callback;")) {
return 1;
}
}
}
break;
case 502538434:
if (var1.equals("intercept")) {
switch(var2.length) {
case 4:
if (var2[0].getName().equals("java.lang.Object") && var2[1].getName().equals("java.lang.reflect.Method") && var2[2].getName().equals("[Ljava.lang.Object;") && var2[3].getName().equals("net.sf.cglib.proxy.MethodProxy")) {
return 14;
}
}
}
break;
case 1154623345:
if (var1.equals("CGLIB$findMethodProxy")) {
switch(var2.length) {
case 1:
if (var2[0].getName().equals("net.sf.cglib.core.Signature")) {
return 0;
}
}
}
break;
case 1543336190:
if (var1.equals("CGLIB$toString$3")) {
switch(var2.length) {
case 0:
return 20;
}
}
break;
case 1811874389:
if (var1.equals("newInstance")) {
switch(var2.length) {
case 1:
String var10001 = var2[0].getName();
switch(var10001.hashCode()) {
case -845341380:
if (var10001.equals("net.sf.cglib.proxy.Callback")) {
return 11;
}
break;
case 1730110032:
if (var10001.equals("[Lnet.sf.cglib.proxy.Callback;")) {
return 10;
}
}
case 2:
default:
break;
case 3:
if (var2[0].getName().equals("[Ljava.lang.Class;") && var2[1].getName().equals("[Ljava.lang.Object;") && var2[2].getName().equals("[Lnet.sf.cglib.proxy.Callback;")) {
return 12;
}
}
}
break;
case 1817099975:
if (var1.equals("setCallback")) {
switch(var2.length) {
case 2:
if (var2[0].getName().equals("int") && var2[1].getName().equals("net.sf.cglib.proxy.Callback")) {
return 15;
}
}
}
break;
case 1891304123:
if (var1.equals("CGLIB$hello$0")) {
switch(var2.length) {
case 1:
if (var2[0].getName().equals("java.lang.String")) {
return 17;
}
}
}
break;
case 1905679803:
if (var1.equals("getCallback")) {
switch(var2.length) {
case 1:
if (var2[0].getName().equals("int")) {
return 4;
}
}
}
break;
case 1951977611:
if (var1.equals("CGLIB$clone$5")) {
switch(var2.length) {
case 0:
return 22;
}
}
}
return -1;
}
public int getIndex(Class[] var1) {
switch(var1.length) {
case 0:
return 0;
default:
return -1;
}
}
public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {
fc037646 var10000 = (fc037646)var2;
int var10001 = var1;
try {
switch(var10001) {
case 0:
return fc037646.CGLIB$findMethodProxy((Signature)var3[0]);
case 1:
var10000.setCallbacks((Callback[])var3[0]);
return null;
case 2:
fc037646.CGLIB$SET_STATIC_CALLBACKS((Callback[])var3[0]);
return null;
case 3:
fc037646.CGLIB$SET_THREAD_CALLBACKS((Callback[])var3[0]);
return null;
case 4:
return var10000.getCallback(((Number)var3[0]).intValue());
case 5:
return var10000.getCallbacks();
case 6:
return new Boolean(var10000.equals(var3[0]));
case 7:
return var10000.toString();
case 8:
return new Integer(var10000.hashCode());
case 9:
return var10000.clone();
case 10:
return var10000.newInstance((Callback[])var3[0]);
case 11:
return var10000.newInstance((Callback)var3[0]);
case 12:
return var10000.newInstance((Class[])var3[0], (Object[])var3[1], (Callback[])var3[2]);
case 13:
return var10000.hello((String)var3[0]);
case 14:
return var10000.intercept(var3[0], (Method)var3[1], (Object[])var3[2], (MethodProxy)var3[3]);
case 15:
var10000.setCallback(((Number)var3[0]).intValue(), (Callback)var3[1]);
return null;
case 16:
fc037646.CGLIB$STATICHOOK1();
return null;
case 17:
return var10000.CGLIB$hello$0((String)var3[0]);
case 18:
return var10000.CGLIB$intercept$1(var3[0], (Method)var3[1], (Object[])var3[2], (MethodProxy)var3[3]);
case 19:
return new Boolean(var10000.CGLIB$equals$2(var3[0]));
case 20:
return var10000.CGLIB$toString$3();
case 21:
return new Integer(var10000.CGLIB$hashCode$4());
case 22:
return var10000.CGLIB$clone$5();
case 23:
CglibTest.main((String[])var3[0]);
return null;
}
} catch (Throwable var4) {
throw new InvocationTargetException(var4);
}
throw new IllegalArgumentException("Cannot find matching method/constructor");
}
public Object newInstance(int var1, Object[] var2) throws InvocationTargetException {
fc037646 var10000 = new fc037646;
fc037646 var10001 = var10000;
int var10002 = var1;
try {
switch(var10002) {
case 0:
var10001.();
return var10000;
}
} catch (Throwable var3) {
throw new InvocationTargetException(var3);
}
throw new IllegalArgumentException("Cannot find matching method/constructor");
}
public int getMaxIndex() {
return 23;
}
}
原生类的FastClass
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package cglib;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import net.sf.cglib.core.Signature;
import net.sf.cglib.proxy.MethodProxy;
import net.sf.cglib.reflect.FastClass;
public class CglibTest$$FastClassByCGLIB$$ef5535a6 extends FastClass {
public CglibTest$$FastClassByCGLIB$$ef5535a6(Class var1) {
super(var1);
}
public int getIndex(Signature var1) {
String var10000 = var1.toString();
switch(var10000.hashCode()) {
case -1249666147:
if (var10000.equals("intercept(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;Lnet/sf/cglib/proxy/MethodProxy;)Ljava/lang/Object;")) {
return 2;
}
break;
case 848333779:
if (var10000.equals("hello(Ljava/lang/String;)Ljava/lang/String;")) {
return 1;
}
break;
case 1341835395:
if (var10000.equals("main([Ljava/lang/String;)V")) {
return 0;
}
break;
case 1826985398:
if (var10000.equals("equals(Ljava/lang/Object;)Z")) {
return 3;
}
break;
case 1913648695:
if (var10000.equals("toString()Ljava/lang/String;")) {
return 4;
}
break;
case 1984935277:
if (var10000.equals("hashCode()I")) {
return 5;
}
}
return -1;
}
public int getIndex(String var1, Class[] var2) {
switch(var1.hashCode()) {
case -1776922004:
if (var1.equals("toString")) {
switch(var2.length) {
case 0:
return 4;
}
}
break;
case -1295482945:
if (var1.equals("equals")) {
switch(var2.length) {
case 1:
if (var2[0].getName().equals("java.lang.Object")) {
return 3;
}
}
}
break;
case 3343801:
if (var1.equals("main")) {
switch(var2.length) {
case 1:
if (var2[0].getName().equals("[Ljava.lang.String;")) {
return 0;
}
}
}
break;
case 99162322:
if (var1.equals("hello")) {
switch(var2.length) {
case 1:
if (var2[0].getName().equals("java.lang.String")) {
return 1;
}
}
}
break;
case 147696667:
if (var1.equals("hashCode")) {
switch(var2.length) {
case 0:
return 5;
}
}
break;
case 502538434:
if (var1.equals("intercept")) {
switch(var2.length) {
case 4:
if (var2[0].getName().equals("java.lang.Object") && var2[1].getName().equals("java.lang.reflect.Method") && var2[2].getName().equals("[Ljava.lang.Object;") && var2[3].getName().equals("net.sf.cglib.proxy.MethodProxy")) {
return 2;
}
}
}
}
return -1;
}
public int getIndex(Class[] var1) {
switch(var1.length) {
case 0:
return 0;
default:
return -1;
}
}
public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {
CglibTest var10000 = (CglibTest)var2;
int var10001 = var1;
try {
switch(var10001) {
case 0:
CglibTest.main((String[])var3[0]);
return null;
case 1:
return var10000.hello((String)var3[0]);
case 2:
return var10000.intercept(var3[0], (Method)var3[1], (Object[])var3[2], (MethodProxy)var3[3]);
case 3:
return new Boolean(var10000.equals(var3[0]));
case 4:
return var10000.toString();
case 5:
return new Integer(var10000.hashCode());
}
} catch (Throwable var4) {
throw new InvocationTargetException(var4);
}
throw new IllegalArgumentException("Cannot find matching method/constructor");
}
public Object newInstance(int var1, Object[] var2) throws InvocationTargetException {
CglibTest var10000 = new CglibTest;
CglibTest var10001 = var10000;
int var10002 = var1;
try {
switch(var10002) {
case 0:
var10001.();
return var10000;
}
} catch (Throwable var3) {
throw new InvocationTargetException(var3);
}
throw new IllegalArgumentException("Cannot find matching method/constructor");
}
public int getMaxIndex() {
return 5;
}
}
我们看下代理类的hello方法
public final String hello(String var1) {
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$hello$0$Method, new Object[]{var1}, CGLIB$hello$0$Proxy) : super.hello(var1);
}
最终调用了 var10000.intercept(this, CGLIB$hello$0$Method, new Object[]{var1}, CGLIB$hello$0$Proxy)方法,也就是我们的
private void init()
{
/*
* Using a volatile invariant allows us to initialize the FastClass and
* method index pairs atomically.
*
* Double-checked locking is safe with volatile in Java 5. Before 1.5 this
* code could allow fastClassInfo to be instantiated more than once, which
* appears to be benign.
*/
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;
}
}
}
}
private static class FastClassInfo
{
FastClass f1;
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();
}
}
}
private static FastClass helper(CreateInfo ci, Class type) {
FastClass.Generator g = new FastClass.Generator();
g.setType(type);
g.setClassLoader(ci.c2.getClassLoader());
g.setNamingPolicy(ci.namingPolicy);
g.setStrategy(ci.strategy);
g.setAttemptLoad(ci.attemptLoad);
return g.create();
}
public class FastClass1 {
public void hello(String name) {
System.out.println("hello, " + name);
}
public void hi(String msg) {
System.out.println("hi, " + msg);
}
}
public class FastClass2 {
public Object invoke(Object obj, int methodIndex, Object[] parameters) {
FastClass1 target = (FastClass1)obj;
Object result = null;
switch (methodIndex) {
case 1:
target.hello((String)parameters[0]);
break;
case 2:
target.hi((String)parameters[0]);
break;
}
return result;
}
public int getIndex(String methodDescriptor) {
switch (methodDescriptor.hashCode()) {
case -2084786067:
return 1;
case -70025314:
return 2;
}
return -1;
}
}
public class FastClassTest {
public static void main(String[] args) {
FastClass1 fastClass1 = new FastClass1();
FastClass2 fastClass2 = new FastClass2();
int helloIndex = fastClass2.getIndex("hello(Ljava/lang/String;)V");//方法名(参数类型;...)返回类型
fastClass2.invoke(fastClass1, helloIndex, new Object[]{"张三"});
int hiIndex = fastClass2.getIndex("hi(Ljava/lang/String;)V");
fastClass2.invoke(fastClass1, hiIndex, new Object[]{"cglib动态代理"});
}
}
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println ("我被代理了");
return proxy.invoke ( obj,args );
}
.........
我被代理了
我被代理了
我被代理了
Exception in thread "main" java.lang.StackOverflowError
at sun.nio.cs.UTF_8.updatePositions(UTF_8.java:77)
at sun.nio.cs.UTF_8.access$200(UTF_8.java:57)
at sun.nio.cs.UTF_8$Encoder.encodeArrayLoop(UTF_8.java:636)
at sun.nio.cs.UTF_8$Encoder.encodeLoop(UTF_8.java:691)
at java.nio.charset.CharsetEncoder.encode(CharsetEncoder.java:579)
at sun.nio.cs.StreamEncoder.implWrite(StreamEncoder.java:271)
at sun.nio.cs.StreamEncoder.write(StreamEncoder.java:125)
at java.io.OutputStreamWriter.write(OutputStreamWriter.java:207)
at java.io.BufferedWriter.flushBuffer(BufferedWriter.java:129)
at java.io.PrintStream.write(PrintStream.java:526)
at java.io.PrintStream.print(PrintStream.java:669)
at java.io.PrintStream.println(PrintStream.java:806)
at cglib.CglibTest.intercept(CglibTest.java:13)
at cglib.CglibTest$$EnhancerByCGLIB$$fc037646.hello()
at cglib.CglibTest$$FastClassByCGLIB$$ef5535a6.invoke()
at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at cglib.CglibTest.intercept(CglibTest.java:14)
at cglib.CglibTest$$EnhancerByCGLIB$$fc037646.hello()
at cglib.CglibTest$$FastClassByCGLIB$$ef5535a6.invoke()
at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at cglib.CglibTest.intercept(CglibTest.java:14)
at cglib.CglibTest$$EnhancerByCGLIB$$fc037646.hello()
at cglib.CglibTest$$FastClassByCGLIB$$ef5535a6.invoke()
at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at cglib.CglibTest.intercept(CglibTest.java:14)
at cglib.CglibTest$$EnhancerByCGLIB$$fc037646.hello()
at cglib.CglibTest$$FastClassByCGLIB$$ef5535a6.invoke()
at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at cglib.CglibTest.intercept(CglibTest.java:14)
at cglib.CglibTest$$EnhancerByCGLIB$$fc037646.hello()
at cglib.CglibTest$$FastClassByCGLIB$$ef5535a6.invoke()
at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at cglib.CglibTest.intercept(CglibTest.java:14)
at cglib.CglibTest$$EnhancerByCGLIB$$fc037646.hello()
at cglib.CglibTest$$FastClassByCGLIB$$ef5535a6.invoke()
at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at cglib.CglibTest.intercept(CglibTest.java:14)
at cglib.CglibTest$$EnhancerByCGLIB$$fc037646.hello()
at cglib.CglibTest$$FastClassByCGLIB$$ef5535a6.invoke()
.........
class CallbackInfo
{
private static final CallbackInfo[] CALLBACKS = {
new CallbackInfo(NoOp.class, NoOpGenerator.INSTANCE),
new CallbackInfo(MethodInterceptor.class, MethodInterceptorGenerator.INSTANCE),
new CallbackInfo(InvocationHandler.class, InvocationHandlerGenerator.INSTANCE),
new CallbackInfo(LazyLoader.class, LazyLoaderGenerator.INSTANCE),
new CallbackInfo(Dispatcher.class, DispatcherGenerator.INSTANCE),
new CallbackInfo(FixedValue.class, FixedValueGenerator.INSTANCE),
new CallbackInfo(ProxyRefDispatcher.class, DispatcherGenerator.PROXY_REF_INSTANCE),
};
}