本篇文章为你整理了java的动态代理底层解析(java的动态代理底层解析怎么做)的详细内容,包含有java的动态代理底层解析怎么写 java的动态代理底层解析怎么做 java动态代理底层原理 java动态代理 java的动态代理底层解析,希望能帮助你了解 java的动态代理底层解析。
1.说明
代理模式的解释:为其他对象提供一种代理以控制对这个对象的访问,增强一个类中的某个方法,对程序进行扩展。
2.类型:
CGLib动态代理和JDK动态代理
3.使用介绍
(1)CGLib动态代理的使用
使用示例:
1、针对代理类的示例
//构建代理对象
public class TestObject {
public void test(){
System.out.println("test");
public void test1(){
System.out.println("test1");
//构建方法拦截器
public class MyMethodInterceptor implements MethodInterceptor {
//Object为由CGLib生成的代理类实例;Method为上文中实体类所调用的被代理的方法引用;Object[]为参数值列表;MethodProxy 为生成的代理类对方法的代理引用
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("before..");
Object result = methodProxy.invokeSuper(o,objects);
System.out.println("after..");
return result;
//生成代理步骤
public static void main(String[] args) {
Enhancer enhancer = new Enhancer(); //构造出加强器对象
enhancer.setSuperclass(TestObject.class); //将代理类设置进去
enhancer.setCallback(new MyMethodInterceptor());
TestObject testObject= (TestObject)enhancer.create();
testObject.test();
}
2、针对代理接口的示例
public interface UserInterface {
public void test();
public void test1();
public class User implements UserInterface {
@Override
public void test() {
System.out.println("test");
@Override
public void test1() {
System.out.println("test1");
public class MyInterfaceMyMethodInterceptor implements MethodInterceptor {
Object object;
public MyInterfaceMyMethodInterceptor(Object object) {
this.object = object;
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("before..");
Object result = methodProxy.invoke(object,objects);
System.out.println("after..");
return result;
public static void main(final String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(UserInterface.class);
enhancer.setCallback(new MyInterfaceMyMethodInterceptor(new User()));
UserInterface userInterface = (UserInterface) enhancer.create();
userInterface.test();
}
(2)JDK动态代理的使用
public interface UserInterface {
public void test();
public void test1();
public class User implements UserInterface {
@Override
public void test() {
System.out.println("test");
@Override
public void test1() {
System.out.println("test1");
public class MyInvocationHandler implements InvocationHandler {
Object target;
public MyInvocationHandler(Object target) {
this.target = target;
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before..");
Object result = method.invoke(target,args);
System.out.println("after..");
return result;
public static void main(String[] args) {
System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
MyInvocationHandler myInvocationHandler = new MyInvocationHandler(new User());
UserInterface userInterface = (UserInterface) Proxy.newProxyInstance(JDKDemo.class.getClassLoader(), new Class[]{UserInterface.class}, myInvocationHandler);
userInterface.test();
}
4.底层分析(通过JVM添加参数-Dcglib.debugLocation=D:\IdeaProjects\cglib\cglib\target\classes【这个便是代理对象的存储路径】)
代理类的class类(依据文件TestObject$$EnhancerByCGLIB$$783a36a0.class)
(1)代码展示
//继承了代理类
public class TestObject$$EnhancerByCGLIB$$783a36a0 extends TestObject 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$test1$1$Method;
private static final MethodProxy CGLIB$test1$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("com.xiangxue.jack.aop.daili.TestObject$$EnhancerByCGLIB$$783a36a0");
Class var1;
//从目标类中拿出对应的方法构建成方法对象
Method[] var10000 = ReflectUtils.findMethods(new String[]{"test", "()V", "test1", "()V"}, (var1 = Class.forName("com.xiangxue.jack.aop.daili.TestObject")).getDeclaredMethods());
CGLIB$test$0$Method = var10000[0];
//针对方法对象构建出代理对象
CGLIB$test$0$Proxy = MethodProxy.create(var1, var0, "()V", "test", "CGLIB$test$0");
CGLIB$test1$1$Method = var10000[1];
CGLIB$test1$1$Proxy = MethodProxy.create(var1, var0, "()V", "test1", "CGLIB$test1$1");
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");
//去执行父类的test()方法
final void CGLIB$test$0() {
super.test();
//重写了父类的test()方法
public final void test() {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this); //给 CGLIB$CALLBACK_0 属性赋值
var10000 = this.CGLIB$CALLBACK_0;
if (var10000 != null) {
//四个参数分别为(当前的代理对象,方法,参数,未知)
var10000.intercept(this, CGLIB$test$0$Method, CGLIB$emptyArgs, CGLIB$test$0$Proxy);
} else {
super.test();
final void CGLIB$test1$1() {
super.test1();
public final void test1() {
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$test1$1$Method, CGLIB$emptyArgs, CGLIB$test1$1$Proxy);
} else {
super.test1();
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 -1422510685:
if (var10000.equals("test()V")) {
return CGLIB$test$0$Proxy;
break;
case -1147892426:
if (var10000.equals("test1()V")) {
return CGLIB$test1$1$Proxy;
break;
case -508378822:
if (var10000.equals("clone()Ljava/lang/Object;")) {
return CGLIB$clone$5$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 TestObject$$EnhancerByCGLIB$$783a36a0() {
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) {
TestObject$$EnhancerByCGLIB$$783a36a0 var1 = (TestObject$$EnhancerByCGLIB$$783a36a0)var0;
if (!var1.CGLIB$BOUND) { //一开始为false,布尔值的默认值
var1.CGLIB$BOUND = true;
Object var10000 = CGLIB$THREAD_CALLBACKS.get(); //从当前线程的ThreadLocal中获取
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);
TestObject$$EnhancerByCGLIB$$783a36a0 var10000 = new TestObject$$EnhancerByCGLIB$$783a36a0();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
public Object newInstance(Callback var1) {
CGLIB$SET_THREAD_CALLBACKS(new Callback[]{var1});
TestObject$$EnhancerByCGLIB$$783a36a0 var10000 = new TestObject$$EnhancerByCGLIB$$783a36a0();
CGLIB$SET_THREAD_CALLBACKS((Callback[])null);
return var10000;
public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) {
CGLIB$SET_THREAD_CALLBACKS(var3);
TestObject$$EnhancerByCGLIB$$783a36a0 var10000 = new TestObject$$EnhancerByCGLIB$$783a36a0;
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();
}
(2)调用流程说明
当代理对象被调用的时候【假设为test()方法】
public final void test() {
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$test$0$Method, CGLIB$emptyArgs, CGLIB$test$0$Proxy);
} else {
super.test();
}
CGLIB$CALLBACK_0该属性一开始是没有值的(因为初始化过程没有赋值的步骤),而获取值得步骤在于CGLIB$BIND_CALLBACKS(this);这一步。
private static final void CGLIB$BIND_CALLBACKS(Object var0) {
TestObject$$EnhancerByCGLIB$$783a36a0 var1 = (TestObject$$EnhancerByCGLIB$$783a36a0)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];
}
这里面var1明显是指类本身,故CGLIB$BOUND会发现是布尔值类型,默认是false。而CGLIB$THREAD_CALLBACKS在静态代码块中被赋予了ThreadLocal,所以是打算从当前线程的ThreadLocal中获取。而CGLIB$STATIC_CALLBACKS类属性值中存放拦截方法数组的地方。然后返回数组的第一个元素过去。(1.这里有个问题ThreadLocal是什么时候被赋值的?)
(3)问题汇总
1.这里有个问题ThreadLocal是什么时候被赋值的?
是在 CGLIB$SET_THREAD_CALLBACKS 这个方法中被赋值的,CGLIB$SET_THREAD_CALLBACKS这个方法又是在newInstance方法【生成代理对象的方法】中被执行。
2.test()⽅法内会去调⽤所设置的Callbacks中的intercept(),相当于执⾏增强逻辑,如果没有Callbacks,则会执⾏super.test(),那么我们⾃然能想到,如果不设置Callbacks,那是不是就能正常执⾏呢?(是不能正常执行的)
异常出现在:createHelper()方法#preValidate()#CallbackInfo.determineTypes(callbacks, false);
会报java.lang.IllegalStateException: Callback is null
createHelper()方法#preValidate()#CallbackInfo.determineTypes(callbacks, false);
会报java.lang.NullPointerException
(4)分析说明
动态代理类持有MethodInterceptor
动态代理类会重写父类的非 final、private 方法【 如test() 】,也会构建自己的方法(cglib 方法),构建方式:CGLIB”+“$父类方法名$【 如CGLIB$test$0】。
cglib 方法的方法体:super.方法名,直接调用父类;重写方法:它会调用拦截器中的intercept()方法。
methodProxy.invokeSuper()方法会调用动态代理类中的 cglib 方法;methodProxy.invoke()方法会调用动态代理类中的重写方法
5.JDK动态代理源码分析(还未写全,待续)
(1)Proxy.newProxyInstance(ClassLoader loader,Class ? [] interfaces,InvocationHandler h)
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader, Class ? [] interfaces, InvocationHandler h) throws IllegalArgumentException {
Objects.requireNonNull(h);
final Class ? [] intfs = interfaces.clone();
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
//去拿到代理类
Class ? cl = getProxyClass0(loader, intfs);
try {
if (sm != null) {
checkNewProxyPermission(Reflection.getCallerClass(), cl);
//拿到代理类的构造方法
final Constructor ? cons = cl.getConstructor(constructorParams);
//拿到拦截器对象
final InvocationHandler ih = h;
if (!Modifier.isPublic(cl.getModifiers())) {
AccessController.doPrivileged(new PrivilegedAction Void () {
public Void run() {
cons.setAccessible(true);
return null;
//然后把拦截器传给构造方法
return cons.newInstance(new Object[]{h});
} catch (IllegalAccessExceptionInstantiationException e) {..} catch (InvocationTargetException e) {...} catch (NoSuchMethodException e) {... }
}
6.CGLib源码分析
(1)Enhancer.create()
public Object create() {
classOnly = false;
argumentTypes = null;
//执行创建
return createHelper();
}
(2)Enhancer.createHelper()
private Object createHelper() {
//校验callbackTypes,filter是否为空,已经为空的处理
preValidate();
// 通过newInstance方法生成了一个EnhancerKey代理对象,该代理对象里面保存了用户所设置的代理信息
Object key = KEY_FACTORY.newInstance((superclass != null) ? superclass.getName() : null,
ReflectUtils.getNames(interfaces),
filter == ALL_ZERO ? null : new WeakCacheKey CallbackFilter (filter),
callbackTypes,
useFactory,
interceptDuringConstruction,
serialVersionUID);
//设置当前Enhancer的代理类的key标识
this.currentKey = key;
// 调用父类AbstractClassGenerator的方法去创建代理对象
Object result = super.create(key);
return result;
}
(3)AbstractClassGenerator.create(Object key)
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);
// 构造方法中会生成一个生成代理类的lambda表达式
data = new ClassLoaderData(loader);
newCache.put(loader, data);
CACHE = newCache;
this.key = key;
// 利用ClassLoaderData拿到代理类,ClassLoaderData中有一个generatedClasses用来缓存生成好的代理类
// this就是Enhancer
Object obj = data.get(this, getUseCache());
if (obj instanceof Class) {
// 调用代理类的构造方法生成一个代理对象
return firstInstance((Class) obj);
return nextInstance(obj);
} catch (RuntimeException e) {...} catch (Error e) {...} catch (Exception e) {...}
}
(4)Enhancer.firstInstance((Class) obj) 与Enhancer.createUsingReflection(type)
protected Object firstInstance(Class type) throws Exception {
if (classOnly) {
return type;
} else {
return createUsingReflection(type);
private Object createUsingReflection(Class type) {
// 设置callbacks到代理类中
setThreadCallbacks(type, callbacks);
try{
if (argumentTypes != null) {
//根据代理类创建代理对象
return ReflectUtils.newInstance(type, argumentTypes, arguments);
} else {
return ReflectUtils.newInstance(type);
}finally{
setThreadCallbacks(type, null);
private static void setThreadCallbacks(Class type, Callback[] callbacks) {
//private static final String SET_THREAD_CALLBACKS_NAME = "CGLIB$SET_THREAD_CALLBACKS";
//这里便是调用将callbacks设置进入ThreadLocal里面
//也就是利用反射区执行
setCallbacksHelper(type, callbacks, SET_THREAD_CALLBACKS_NAME);
}
(5)ClassLoaderData.get(this, getUseCache())
public Object get(AbstractClassGenerator gen, boolean useCache) {
if (!useCache) {//也就是enhancer.setUseCache(false);会起到作用的地方,
// gen是Enhancer, ClassLoaderData.this中存储了EnhancerKey代理对象
return gen.generate(ClassLoaderData.this);
} else {//这里使用到缓存useCache=true
Object cachedValue = generatedClasses.get(gen);
return gen.unwrapCachedValue(cachedValue);
//Enhancer.generate
protected Class generate(ClassLoaderData data) {
validate();
//类的名字(可参考文件的名字)
if (superclass != null) {
setNamePrefix(superclass.getName());
} else if (interfaces != null) {
setNamePrefix(interfaces[ReflectUtils.findPackageProtected(interfaces)].getName());
//AbstractClassGenerator.generate
return super.generate(data);
//AbstractClassGenerator.generate
protected Class generate(ClassLoaderData data) {
Class gen;
Object save = CURRENT.get();
CURRENT.set(this);
try {
ClassLoader classLoader = data.getClassLoader();
if (classLoader == null) { throw ex..;}
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) {..}
// this就是Enhancer,主要是在这个方法里面利用ASM技术,生成代理类里面的东西
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) {..} catch (Error e) {..} catch (Exception e) {..} finally {
CURRENT.set(save);
//代码generatedClasses.get(gen)进入
public V get(K key) {
// 这里得到就是EnhancerKey的代理对象
final KK cacheKey = keyMapper.apply(key);
Object v = map.get(cacheKey);
if (v != null !(v instanceof FutureTask)) {
return (V) v;
// 传进去的key为Enhancer对象,cacheKey为EnhancerKey的代理对象,表示所设置的代理信息
return createEntry(key, cacheKey, v);
public V call() throws Exception {
// 这里就会去创建代理类了,实际上也是调用gen.generate(ClassLoaderData.this);
return loader.apply(key);
Object prevTask = map.putIfAbsent(cacheKey, task);
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 {
result = task.get();
} catch (InterruptedException e) {...} catch (ExecutionException e) {...}
if (creator) {
// 代理类创建完之后会进行缓存
map.put(cacheKey, result);
return result;
}
7.MethodProxy源码分析
代码展示
public class UserService {
public void test(){
System.out.println("test");
public static void main(String[] args) {
final UserService target = new UserService();
Enhancer enhancer = new Enhancer();
enhancer.setUseCache(false);
enhancer.setSuperclass(UserService.class);
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
//为什么会存在有些报错有些不报错的问题?
if (method.getName().equals("test")) {
System.out.println("before...");
methodProxy.invoke(o, objects); //报栈溢出错误
methodProxy.invoke(target, objects);
methodProxy.invokeSuper(o, objects);
methodProxy.invokeSuper(target, objects); //报调⽤invokerSuper只能传⼊代理对象的错误
System.out.println("after...");
return null;
return method.invoke(target, objects);
UserService userService = (UserService) enhancer.create();
userService.test();
}
代码说明
在使用过程,我们常常遇到methodProxy上的方法使用问题,然而根本不知道为什么会这样。(虽然也不怎么会这样用)
进行分析
(1)MethodProxy是什么时候创建出来的?
从上面的字节码文件可以看到是在静态方法CGLIB$STATICHOOK1()中生成的。
源代码为(MethodProxy类#create方法)
create(Class c1, Class c2, String desc, String name1, String name2) {
// c1是TestObject
// c2是TestObject代理类[TestObject$$EnhancerByCGLIB$$783a36a0]
// desc被代理方法的返回值类型
// name1是被代理方法名比如test
// name2是代理类中的CGLIB$test$0方法,会调用super.test()
MethodProxy proxy = new MethodProxy();
proxy.sig1 = new Signature(name1, desc); // 被代理方法签名,也就是代表void test()
proxy.sig2 = new Signature(name2, desc); // 代理方法签名,也就是void CGLIB$test$0()
proxy.createInfo = new CreateInfo(c1, c2); // CreateInfo中表示的就是被代理类和代理类的信息
return proxy;
}
(2)MethodProxy的invoke方法与invokeSuper方法的区别?
先上代码:
public Object invoke(Object obj, Object[] args) throws Throwable {
try {
init();
FastClassInfo fci = fastClassInfo;
// f1表示被代理类的FastClass代理类,i1表示被代理方法的下标,这里就是去执行test()方法,具体执行的是哪个对象就看obj
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;
public Object invokeSuper(Object obj, Object[] args) throws Throwable {
try {
init();
FastClassInfo fci = fastClassInfo;
// f2表示UserService代理类的FastClass代理类,i2表示代理方法的下标,这里就是去执行CGLIB$test$0方法,具体执行的是哪个对象就看obj
return fci.f2.invoke(fci.i2, obj, args);
} catch (InvocationTargetException e) {
throw e.getTargetException();
}
说明
1.说白了,这个两个方法本身是根据不同的索引文件去找对应的方法,然后用传入对象,调用返回的方法。
2.这里面涉及了另外的两个字节码文件(便是上面存储路径下的):
TestObject$$EnhancerByCGLIB$$783a36a0$$FastClassByCGLIB$$626f6578.class(这里面是代理类的方法索引)
TestObject$$FastClassByCGLIB$$a3bbba2f.class(这里面是目标类的方法索引)
(3)FastClassInfo的生成过程
private void init(){
if (fastClassInfo == null) {
//采用双重判断+加锁达到只生成一次
synchronized (initLock) {
if (fastClassInfo == null) {
// CreateInfo中存储了代理类和被代理类
CreateInfo ci = createInfo;
FastClassInfo fci = new FastClassInfo();
fci.f1 = helper(ci, ci.c1); // 被代理类的FastClass代理类,也就是TestObject$$FastClassByCGLIB$$a3bbba2f.class
fci.f2 = helper(ci, ci.c2); // 代理类的FastClass代理类,也就是TestObject$$EnhancerByCGLIB$$783a36a0$$FastClassByCGLIB$$626f6578.class
// 预先生成每个方法所对应的下标,调用时就可以直接利用下标找到方法了,性能高
fci.i1 = fci.f1.getIndex(sig1); // 获取方法签名sig1在被代理类的FastClass代理类中的下标,后续根据下标找到对应的方法,sig1表示被代理方法test()
fci.i2 = fci.f2.getIndex(sig2); // 获取方法签名sigsig2在代理类的FastClass代理类中的下标,后续根据下标找到对应的方法,sig2表示代理方法CGLIB$test$0()
fastClassInfo = fci;
createInfo = null;
}
TestObject$$EnhancerByCGLIB$$783a36a0$$FastClassByCGLIB$$626f6578.class代码展示(已经进行了部分删。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。