cglib源码主流程源码-我们到底能走多远系列48
扯淡
祝各位在园里的朋友新年快乐!
辛苦一年,为更好的自己也为更好的世界,很多人要感谢你们,你们也应该有很多人要感谢吧。
看了马斯克的采访视频,又想起兰迪·鲍许的最后一课,时光迁移,唯有梦想可坚持。
概念
在java的世界里,基于jvm实现的语言最终要进入jvm编译的流程都需要把上层高级语言所表达的内容自行编译成字节码文件,而cglib是一个操作字节码生成自定义类的库,它底层调用的是ASM库来操作字节码的。示意图:
这里主要以使用cglib入口为起点进入它源代码,详细查看内部的实现机制。
具体实现流程
AbstractClassGenerator是CGLIB 核心类,这个抽象类作为CGLIB中代码生成调度员角色,做了缓存,定制ClassLoader,命名。
Enhancer 继承 AbstractClassGenerator
从Enhancer中的crate方法系列开始这场旅行。
以下三个方法用classOnly参数来控制返回的是Class对象,还是代理对象本身。所以我们可以知道在调用createHelper方法的时候这两个对象是要生成的。
/**
*
* 入口方法,产生一个代理对象
* @return a new instance
*/
public Object create() {
classOnly = false;
argumentTypes = null;
return createHelper();
}
public Object create(Class[] argumentTypes, Object[] arguments) {
classOnly = false;
if (argumentTypes == null || arguments == null || argumentTypes.length != arguments.length) {
throw new IllegalArgumentException("Arguments must be non-null and of equal length");
}
this.argumentTypes = argumentTypes;
this.arguments = arguments;
return createHelper();
}
public Class createClass() {
classOnly = true;
return (Class)createHelper();
}
静态的crate方法:
public static Object create(Class type, Callback callback) {
Enhancer e = new Enhancer();
e.setSuperclass(type);
e.setCallback(callback);
return e.create();
}
public static Object create(Class superclass, Class interfaces[], Callback callback) {
Enhancer e = new Enhancer();
e.setSuperclass(superclass);
e.setInterfaces(interfaces);
e.setCallback(callback);
return e.create();
}
public static Object create(Class superclass, Class[] interfaces, CallbackFilter filter, Callback[] callbacks) {
Enhancer e = new Enhancer();
e.setSuperclass(superclass);
e.setInterfaces(interfaces);
e.setCallbackFilter(filter);
e.setCallbacks(callbacks);
return e.create();
}
都是new 一个Enhancer然后进行操作,最后都调用create()方法,提供给外部调用者不同的调用方式,我们可以看到至多需要以下几个元素:
- Class superclass
- Class[] interfaces
- CallbackFilter filter
- Callback[] callbacks
那么最后这些方法在设置好变量后,都会调用到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;
// 调用AbstractClassGenerator.create(Object)方法
Object result = super.create(key);
return result;
}
AbstractClassGenerator.create(Object)方法:
protected Object create(Object key) {
try {
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;
// 这里产生class对象 背后有做缓存功能
Object obj = data.get(this, getUseCache());
if (obj instanceof Class) {
// 模版方法 用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);
}
}
abstract protected Object firstInstance(Class type) throws Exception;
abstract protected Object nextInstance(Object instance) throws Exception;
我们看到firstInstance 和 nextInstance模版方法给子类实现,
而在进入执行子类模版方法前,代理类的class字节码必然已经组装好了。
Object obj = data.get(this, getUseCache());
这行获取class实例或者EnhancerFactoryData,返回的类型也是判断执行firstInstance 或 nextInstance的依据。这里就是组装类字节码,缓存类信息等操作的入口。后续展开
先看一下看Enhancer的两个实例化入口的实现:
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);
}
classOnly字段控制返回类型,从代码实现上来看nextInstance是firstInstance的升级版,在firstInstance上的原文注释上我们也可以印证,实际自定义代理类在创建时是不会调用到firstInstance而是调用nextInstance,而nextInstance中是做类一个缓存功能。
而我们可以查看上面连个方法要实例化出对象最终都会调用到ReflectUtils.newInstance(final Constructor cstruct, final Object[] args)方法。查看方法我们发现是用cstruct.newInstance(args)这行代码来实现的:
public static Object newInstance(final Constructor cstruct, final Object[] args) {
boolean flag = cstruct.isAccessible();
try {
if (!flag) {
cstruct.setAccessible(true);
}
// 最终调用 产生代理对象
Object result = cstruct.newInstance(args);
return result;
} catch (InstantiationException e) {
throw new CodeGenerationException(e);
} catch (IllegalAccessException e) {
throw new CodeGenerationException(e);
} catch (InvocationTargetException e) {
throw new CodeGenerationException(e.getTargetException());
} finally {
if (!flag) {
cstruct.setAccessible(flag);
}
}
}
传入nextInstance方法的是EnhancerFactoryData实例。 EnhancerFactoryData中保存了以下这些内容:
public final Class generatedClass;
private final Method setThreadCallbacks;
private final Class[] primaryConstructorArgTypes;
private final Constructor primaryConstructor;
到这里我们就明白了nextInstance是firstInstance升级版的意义,就是把Constructor缓存起来在每次要实例化时不需要像firstInstance那样调用下面的代码去遍历出Constructor:
public static Constructor getConstructor(Class type, Class[] parameterTypes) {
try {
// 这一步就是nextInstance在省略的
Constructor constructor = type.getDeclaredConstructor(parameterTypes);
constructor.setAccessible(true);
return constructor;
} catch (NoSuchMethodException e) {
throw new CodeGenerationException(e);
}
}
前面提到Object obj = data.get(this, getUseCache());返回组装好字节码的代理类或包装类EnhancerFactoryData,用于实例化代理类。
调用到AbstractClassGenerator中的内部类ClassLoaderData的方法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);
}
}
从上面的代码有不使用缓存的逻辑就直接调用AbstractClassGenerator.generate(ClassLoaderData data)方法。看名字就知道这个是核心方法了,而用走缓存分支肯定也是要调这个方法,只是多了一份缓存的逻辑。
generatedClasses 是一个LoadingCache类,这个LoadingCache是用于存储的设计类:
// 实际存储map
protected final ConcurrentMap<KK, Object> map;
protected final Function<K, V> loader;
// 名字是map 其实是封装了获得kk的算法 获取是调用apply方法
protected final Function<K, KK> keyMapper;
Function类是一个函数接口(Functional Interface):
public interface Function<K, V> {
V apply(K key);
}
可以理解为带某个自定义算法的类,可以传送给其他类使用。
LoadingCache类中的核心方法get(K key)(其中key后续进行详细分析),最终会调用到createEntry,:
public V get(K key) {
// 包装key的算法
final KK cacheKey = keyMapper.apply(key);
Object v = map.get(cacheKey);
// 如果是FutureTask 则说明还在创建中,如果不是FutureTask,则说明已经创建好可直接返回
if (v != null && !(v instanceof FutureTask)) {
return (V) v;
}
return createEntry(key, cacheKey, v);
}
protected V createEntry(final K key, KK cacheKey, Object v) {
FutureTask<V> task;
// 标记是一个新建的流程
boolean creator = false;
// v有值说明是已经找到在执行的FutureTask
if (v != null) {
// Another thread is already loading an instance
task = (FutureTask<V>) v;
} else {
//新建一个FutureTask
task = new FutureTask<V>(new Callable<V>() {
public V call() throws Exception {
// task执行内容
return loader.apply(key);
}
});
// putIfAbsent判断是否已经有值
Object prevTask = map.putIfAbsent(cacheKey, task);
// 三种情况
// 1,没值 则是新放的task 就启动这个task
// 2,有值 是FutureTask 说明有线程在我执行putIfAbsent之前已经捷足先登了 那就把自己新建的task抛弃掉
// 3,有值 不是FutureTask 说明已经有task已经执行完成并放入了result 那就直接返回这个resutl即可
if (prevTask == null) {
// creator does the load
creator = true;
task.run();
} else if (prevTask instanceof FutureTask) {
task = (FutureTask<V>) prevTask;
} else {
return (V) prevTask;
}
}
V result;
try {
// task执行完毕返回值
result = task.get();
} 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) {
// 放缓存
map.put(cacheKey, result);
}
return result;
}
}
以上代码详细解读后发现是这样设计的:
1,用ConcurrentMap存储,先放的value是FutureTask,执行完成后value放执行结果,并保证在FutureTask放入之后,再不能进行替换操作,无论是否执行完毕。
2,利用FutureTask异步获取执行结果的能力把编织字节码的过程异步化,新的线程获取同一个代理类时,因为保证在放入map后的task只执行一次,也就没有并发情况是多个相同代理类的编织消耗了。
下面画了示意图:
这个设计的场景应该是比较常见的,产生一个对象比较消耗,这时候自然会想到把它缓存起来,一般的写法就向下面的代码:
先组装这个对象,然后放入缓存,放入的时候判断是否已存在。但是这种写法在高并发时一波线程全部同时到达第一步代码,然后都去执行消耗的代码,然后进入第二步的时候就要不断替换,虽然最后的结果可能是正确的,不过会有无谓的浪费。现在再看一下cglib的实现就可以学到了。
Object object = create();//1
map.putIfAbsent(key, obj);//2
这里详细再展开下,因为这也是非常值得学习的地方,我们想如果我们并不想用异步的方式呢?以下是一个网上解决方案,很有意思:
public class concurrentMapTest {
// 记录自旋状态的轻量级类,只封装了一个volatile状态
public static class SpinStatus{
volatile boolean released;
}
// 辅助并发控制的Map,用来找出每个key对应的第一个成功进入的线程
private ConcurrentMap<String, SpinStatus> raceUtil = new ConcurrentHashMap<String, SpinStatus>();
private ConcurrentMap<String, Object> map = new ConcurrentHashMap<String, Object>();
public Object test(String key){
Object value = map.get(key);
// 第一次
if(value == null){
// 需要为并发的线程new一个自旋状态,只有第一个成功执行putIfAbsent方法的线程设置的SpinStatus会被共享
SpinStatus spinStatus = new SpinStatus();
SpinStatus oldSpinStatus = raceUtil.putIfAbsent(key, spinStatus);
//只有第一个执行成功的线程拿到的oldSpinStatus是null,其他线程拿到的oldSpinStatus是第一个线程设置的,可以在所有线程中共享
if(oldSpinStatus == null){
value = create();
// 放入共享的并发Map,后续线程执行get()方法后可以直接拿到非null的引用返回
map.put(key, value);
// 释放其他自旋的线程,注意,对第一个成功执行的线程使用的是spinStatus的引用
spinStatus.released = true;
}else{
// 其他线程在oldSpinStatus引用所指向的共享自旋状态上自旋,等待被释放
while(!oldSpinStatus.released){};
}
// 再次获取一下,这时候是肯定不为空
value = map.get(key);
}
return value;
}
/**
* 假装耗时代码
* @return
*/
public static String create(){
return "1";
}
}
新建task的代码就是组装代理类的代码,但是这个return loader.apply(key);里的load是调用方传入的,我们看下调用方的代码:
先打开ClassLoaderData的代码,它是AbstractClassGenerator的内部类:
protected static class ClassLoaderData {
private final Set<String> reservedClassNames = new HashSet<String>();
private final LoadingCache<AbstractClassGenerator, Object, Object> generatedClasses;
private final WeakReference<ClassLoader> classLoader;
private final Predicate uniqueNamePredicate = new Predicate() {
public boolean evaluate(Object name) {
return reservedClassNames.contains(name);
}
};
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);
// 组装load
Function<AbstractClassGenerator, Object> load =
new Function<AbstractClassGenerator, Object>() {
public Object apply(AbstractClassGenerator gen) {
Class klass = gen.generate(ClassLoaderData.this);
return gen.wrapCachedClass(klass);
}
};
// 组装LoadingCache代码
generatedClasses = new LoadingCache<AbstractClassGenerator, Object, Object>(GET_KEY, load);
}
public ClassLoader getClassLoader() {
return classLoader.get();
}
public void reserveName(String name) {
reservedClassNames.add(name);
}
public Predicate getUniqueNamePredicate() {
return uniqueNamePredicate;
}
public Object get(AbstractClassGenerator gen, boolean useCache) {
if (!useCache) {
return gen.generate(ClassLoaderData.this);
} else {
Object cachedValue = generatedClasses.get(gen);
return gen.unwrapCachedValue(cachedValue);
}
}
}
直接取出loader.apply(key);的代码:
public Object apply(AbstractClassGenerator gen) {
Class klass = gen.generate(ClassLoaderData.this);
return gen.wrapCachedClass(klass);
}
首先调用的是
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
}
}
// 调用strategy的generate
byte[] b = strategy.generate(this);
String className = ClassNameReader.getClassName(new ClassReader(b));
ProtectionDomain protectionDomain = getProtectionDomain();
synchronized (classLoader) { // just in case
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);
}
}
调用strategy的generate:
public byte[] generate(ClassGenerator cg) throws Exception {
// DebuggingClassWriter中DEBUG_LOCATION_PROPERTY可以设置代理类class文件的路径
DebuggingClassWriter cw = getClassVisitor();
transform(cg).generateClass(cw);
return transform(cw.toByteArray());
}
最后还是调用到net.sf.cglib.proxy.Enhancer#generateClass 而这个方法是ClassGenerator接口定义要实现的方法。
因为在Enhancer中已经保存了编织代理类的全部信息,编织过程的入口由自己来实现。这里就不再继续深入研究字节码编织的过程,因为这需要理解asm的api和class文件格式已经jvm编译规范。后续的学习过程中将补全这部分内容。
那么至此基本写完类以cglib产生代理类的主流程。
反编译例子
以下是一个例子附加了代理类的反编译代码:
被代理类:
public class SampleClass {
public String test(String input) {
return "Hello world!";
}
public void big(String i){
System.out.println("1111");
}
public int test1(String input) {
return 1;
}
}
操作类:
public void testMethodInterceptor() throws Exception {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(SampleClass.class);
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy)
throws Throwable {
if(method.getDeclaringClass() != Object.class && method.getReturnType() == String.class) {
return "Hello cglib!";
} else {
return proxy.invokeSuper(obj, args);
}
}
});
SampleClass proxy = (SampleClass) enhancer.create();
}
我们可以通过下面代码的设置将cglib产生的代理类生成到自定义的路径上去,方便自己反编译:
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "/gitwork/");
反编译后代码,我们可以直接看到它继承了SampleClass类,然后在test方法实现的地方做了处理:
package com.hope.learn.third.cglib;
import com.hope.learn.third.cglib.SampleClass;
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 SampleClass$$EnhancerByCGLIB$$a2b2935d extends SampleClass 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$test$0$Method;
private static final MethodProxy CGLIB$test$0$Proxy;
private static final Object[] CGLIB$emptyArgs;
private static final Method CGLIB$big$1$Method;
private static final MethodProxy CGLIB$big$1$Proxy;
private static final Method CGLIB$test1$2$Method;
private static final MethodProxy CGLIB$test1$2$Proxy;
private static final Method CGLIB$equals$3$Method;
private static final MethodProxy CGLIB$equals$3$Proxy;
private static final Method CGLIB$toString$4$Method;
private static final MethodProxy CGLIB$toString$4$Proxy;
private static final Method CGLIB$hashCode$5$Method;
private static final MethodProxy CGLIB$hashCode$5$Proxy;
private static final Method CGLIB$clone$6$Method;
private static final MethodProxy CGLIB$clone$6$Proxy;
static void CGLIB$STATICHOOK1() {
CGLIB$THREAD_CALLBACKS = new ThreadLocal();
CGLIB$emptyArgs = new Object[0];
Class var0 = Class.forName("com.hope.learn.third.cglib.SampleClass$$EnhancerByCGLIB$$a2b2935d");
Class var1;
Method[] var10000 = ReflectUtils.findMethods(new String[]{"test", "(Ljava/lang/String;)Ljava/lang/String;", "big", "(Ljava/lang/String;)V", "test1", "(Ljava/lang/String;)I"}, (var1 = Class.forName("com.hope.learn.third.cglib.SampleClass")).getDeclaredMethods());
CGLIB$test$0$Method = var10000[0];
CGLIB$test$0$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/String;)Ljava/lang/String;", "test", "CGLIB$test$0");
CGLIB$big$1$Method = var10000[1];
CGLIB$big$1$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/String;)V", "big", "CGLIB$big$1");
CGLIB$test1$2$Method = var10000[2];
CGLIB$test1$2$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/String;)I", "test1", "CGLIB$test1$2");
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$3$Method = var10000[0];
CGLIB$equals$3$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/Object;)Z", "equals", "CGLIB$equals$3");
CGLIB$toString$4$Method = var10000[1];
CGLIB$toString$4$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/String;", "toString", "CGLIB$toString$4");
CGLIB$hashCode$5$Method = var10000[2];
CGLIB$hashCode$5$Proxy = MethodProxy.create(var1, var0, "()I", "hashCode", "CGLIB$hashCode$5");
CGLIB$clone$6$Method = var10000[3];
CGLIB$clone$6$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/Object;", "clone", "CGLIB$clone$6");
}
final String CGLIB$test$0(String var1) {
return super.test(var1);
}
public final String test(String var1) {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if(this.CGLIB$CALLBACK_0 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
return var10000 != null?(String)var10000.intercept(this, CGLIB$test$0$Method, new Object[]{var1}, CGLIB$test$0$Proxy):super.test(var1);
}
final void CGLIB$big$1(String var1) {
super.big(var1);
}
public final void big(String var1) {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if(this.CGLIB$CALLBACK_0 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
if(var10000 != null) {
var10000.intercept(this, CGLIB$big$1$Method, new Object[]{var1}, CGLIB$big$1$Proxy);
} else {
super.big(var1);
}
}
final int CGLIB$test1$2(String var1) {
return super.test1(var1);
}
public final int test1(String var1) {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if(this.CGLIB$CALLBACK_0 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
if(var10000 != null) {
Object var2 = var10000.intercept(this, CGLIB$test1$2$Method, new Object[]{var1}, CGLIB$test1$2$Proxy);
return var2 == null?0:((Number)var2).intValue();
} else {
return super.test1(var1);
}
}
final boolean CGLIB$equals$3(Object var1) {
return super.equals(var1);
}
public final boolean equals(Object var1) {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if(this.CGLIB$CALLBACK_0 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
if(var10000 != null) {
Object var2 = var10000.intercept(this, CGLIB$equals$3$Method, new Object[]{var1}, CGLIB$equals$3$Proxy);
return var2 == null?false:((Boolean)var2).booleanValue();
} else {
return super.equals(var1);
}
}
final String CGLIB$toString$4() {
return super.toString();
}
public final String toString() {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if(this.CGLIB$CALLBACK_0 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
return var10000 != null?(String)var10000.intercept(this, CGLIB$toString$4$Method, CGLIB$emptyArgs, CGLIB$toString$4$Proxy):super.toString();
}
final int CGLIB$hashCode$5() {
return super.hashCode();
}
public final int hashCode() {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if(this.CGLIB$CALLBACK_0 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
if(var10000 != null) {
Object var1 = var10000.intercept(this, CGLIB$hashCode$5$Method, CGLIB$emptyArgs, CGLIB$hashCode$5$Proxy);
return var1 == null?0:((Number)var1).intValue();
} else {
return super.hashCode();
}
}
final Object CGLIB$clone$6() throws CloneNotSupportedException {
return super.clone();
}
protected final Object clone() throws CloneNotSupportedException {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if(this.CGLIB$CALLBACK_0 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
return var10000 != null?var10000.intercept(this, CGLIB$clone$6$Method, CGLIB$emptyArgs, CGLIB$clone$6$Proxy):super.clone();
}
public static MethodProxy CGLIB$findMethodProxy(Signature var0) {
String var10000 = var0.toString();
switch(var10000.hashCode()) {
case -1315810049:
if(var10000.equals("big(Ljava/lang/String;)V")) {
return CGLIB$big$1$Proxy;
}
break;
case -508378822:
if(var10000.equals("clone()Ljava/lang/Object;")) {
return CGLIB$clone$6$Proxy;
}
break;
case -178329709:
if(var10000.equals("test(Ljava/lang/String;)Ljava/lang/String;")) {
return CGLIB$test$0$Proxy;
}
break;
case 992023923:
if(var10000.equals("test1(Ljava/lang/String;)I")) {
return CGLIB$test1$2$Proxy;
}
break;
case 1826985398:
if(var10000.equals("equals(Ljava/lang/Object;)Z")) {
return CGLIB$equals$3$Proxy;
}
break;
case 1913648695:
if(var10000.equals("toString()Ljava/lang/String;")) {
return CGLIB$toString$4$Proxy;
}
break;
case 1984935277:
if(var10000.equals("hashCode()I")) {
return CGLIB$hashCode$5$Proxy;
}
}
return null;
}
public SampleClass$$EnhancerByCGLIB$$a2b2935d() {
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) {
SampleClass$$EnhancerByCGLIB$$a2b2935d var1 = (SampleClass$$EnhancerByCGLIB$$a2b2935d)var0;
if(!var1.CGLIB$BOUND) {
var1.CGLIB$BOUND = true;
Object var10000 = CGLIB$THREAD_CALLBACKS.get();
if(var10000 == null) {
var10000 = CGLIB$STATIC_CALLBACKS;
if(CGLIB$STATIC_CALLBACKS == null) {
return;
}
}
var1.CGLIB$CALLBACK_0 = (MethodInterceptor)((Callback[])var10000)[0];
}
}
public Object newInstance(Callback[] var1) {
CGLIB$SET_THREAD_CALLBACKS(var1);
SampleClass$$EnhancerByCGLIB$$a2b2935d var10000 = new SampleClass$$EnhancerByCGLIB$$a2b2935d();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
}
public Object newInstance(Callback var1) {
CGLIB$SET_THREAD_CALLBACKS(new Callback[]{var1});
SampleClass$$EnhancerByCGLIB$$a2b2935d var10000 = new SampleClass$$EnhancerByCGLIB$$a2b2935d();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
}
public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) {
CGLIB$SET_THREAD_CALLBACKS(var3);
SampleClass$$EnhancerByCGLIB$$a2b2935d var10000 = new SampleClass$$EnhancerByCGLIB$$a2b2935d;
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();
}
}
原文git更新地址
让我们继续前行
努力不一定成功,但不努力肯定不会成功。
cglib源码主流程源码-我们到底能走多远系列48的更多相关文章
- Bean实例化(Spring源码阅读)-我们到底能走多远系列(33)
我们到底能走多远系列(33) 扯淡: 各位: 命运就算颠沛流离 命运就算曲折离奇 命运就算恐吓着你做人没趣味 别流泪 心酸 更不应舍弃 ... 主题: Spring源码阅读还在继 ...
- Spring mvc源码url路由-我们到底能走多远系列(38)
我们到底能走多远系列38 扯淡: 马航的事,挺震惊的.还是多多珍惜身边的人吧. 主题: Spring mvc 作为表现层的框架,整个流程是比较好理解的,毕竟我们做web开发的,最早也经常接触的就是一个 ...
- 初始化IoC容器(Spring源码阅读)-我们到底能走多远系列(31)
我们到底能走多远系列(31) 扯淡: 有个问题一直想问:各位你们的工资剩下来会怎么处理?已婚的,我知道工资永远都是不够的.未婚的你们,你们是怎么分配工资的? 毕竟,对自己的收入的分配差不多体现了自己的 ...
- ArrayBlockingQueue-我们到底能走多远系列(42)
我们到底能走多远系列(42) 扯淡: 乘着有空,读些juc的源码学习下.后续把juc大致走一边,反正以后肯定要再来. 主题: BlockingQueue 是什么 A java.util.Queue t ...
- ThreadPoolExecutor机制探索-我们到底能走多远系列(41)
我们到底能走多远系列(41) 扯淡: 这一年过的不匆忙,也颇多感受,成长的路上难免弯路,这个世界上没人关心你有没有变强,只有自己时刻提醒自己,不要忘记最初出发的原因. 其实这个世界上比我们聪明的人无数 ...
- 服务调用方案(Spring Http Invoker) - 我们到底能走多远系列(40)
我们到底能走多远系列(40) 扯淡: 判断是否加可以效力于这家公司,一个很好的判断是,接触下这公司工作几年的员工,了解下生活工作状态,这就是你几年后的状态,如果满意就可以考虑加入了. 主题: 场景: ...
- node模拟http服务器session机制-我们到底能走多远系列(36)
我们到底能走多远系列(36) 扯淡: 年关将至,总是会在一些时间节点上才感觉时光飞逝,在平时浑浑噩噩的岁月里都浪费掉了太多的宝贵.请珍惜! 主题: 我们在编写http请求处理和响应的代码的时 ...
- html5实现饼图和线图-我们到底能走多远系列(34)
我们到底能走多远系列(34) 扯淡: 送给各位一段话: 人生是一个不断做加法的过程 从赤条条无牵无挂的来 到学会荣辱羞耻 礼仪规范 再到赚取世间的名声 财富 地位 ...
- ajax简单后台交互-我们到底能走多远系列(28)
我们到底能走多远系列(28) 1,扯淡 单身的生活,大部分时间享受自由,小部分时间忍受寂寞. 生活有时候,其实蛮苦涩,让人难以下咽.那些用岁月积累起来的苦闷,无处宣泄,在自己的脑海里蔓延成一片片荆棘, ...
随机推荐
- Java学习之类的构建方法(函数)
在学习类的部分时,建立一个对象是这样建立的:(假设Person是类)Person p = new Person():我一直很费解为何new后面是一个函数形式, 今天学完构建方法后,才恍然大悟,豁然 ...
- Function方法和属性图
- POJ 3829 Seat taking up is tough(——只是题目很长的模拟)
题目链接: http://poj.org/problem?id=3829 题意描述: 输入矩阵的大小n和m,以及来占位置的人数k 输入n*m的教室座位矩阵,每个值表示该座位的满意度 输入每个人来占位置 ...
- LNMP安装Let’s Encrypt 免费SSL证书方法:自动安装与手动配置Nginx
前几天介绍了最新StartSSL免费SSL申请与配置,很多人看到部落介绍SSL证书安装时总是推荐了OneinStack,因为OneinStack提供了一键添加和配置Let's Encrypt 免费SS ...
- nginx 防火墙、权限问题
1.nginx安装,配置完成之后,尝试访问没有响应,主机可以ping通,/var/log/nginx/access.log日志没有查到任何记录 解决方法:查看linux防火墙,关闭 命令:ipta ...
- SVN版本库修改URL路径或者IP地址
服务器的IP地址或者URL变更,版本库服务器的IP也要修改,因为当初安装SVN URL没有使用别名,所以使用的人都要修改客户端的IP,以下是参考网上的资料. 1.Windows TortoiseSVN ...
- 虚拟主机导入MySQL出现Unknown character set: ‘utf8mb4’
http://www.lmlblog.com/14.html 前几天进行网站搬家,MySQL导入数据的时候,出现以下错误(没有定义的编码集utf8mb4): SQL 查询: ; MySQL 返回:文档 ...
- Django权限机制的实现
Django权限机制的实现 1. Django权限机制概述 权限机制能够约束用户行为,控制页面的显示内容,也能使API更加安全和灵活:用好权限机制,能让系统更加强大和健壮.因此,基于Django的开发 ...
- zabbix自动清理30天前的数据
转:http://www.361way.com/delete-zabbix-histroy-data/3826.html zabbix属于一个细度化的监控工具,其入库数据随着细度的增加相应的入库数据量 ...
- 数据流(任务并行库 TPL)
TPL 数据流库向具有高吞吐量和低滞后时间的占用大量 CPU 和 I/O 操作的应用程序的并行化和消息传递提供了基础. 它还能显式控制缓存数据的方式以及在系统中移动的方式. 为了更好地了解数据流编程模 ...