Cglib代理解密
发布日期:2022-02-26 14:49:34 浏览次数:53 分类:技术文章

本文共 44312 字,大约阅读时间需要 147 分钟。

Cglib代理原理解密

cglib与动态代理功能类似,都是为了做方法拦截的,从而增强方法功能,本文讲解cglib的原理

我有一个CglibDemo类,也就是main方法的测试类, 他有一个属性name和他的get set方法

import net.sf.cglib.core.DebuggingClassWriter;import net.sf.cglib.proxy.Enhancer;import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.MethodProxy;import java.lang.reflect.Method;/** * @author hh * @date 2020/9/29 */public class CglibDemo {
public static void main(String[] args) throws Exception{
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "c:\\classes"); Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(CglibDemo.class); enhancer.setCallback(new MethodInterceptor() {
@Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("before..."); Object result = proxy.invokeSuper(obj, args); System.out.println("after ..."); return result; } }); CglibDemo cglibProxy = (CglibDemo) enhancer.create(); cglibProxy.getName(); } private String name; public String getName() {
System.out.println("get name..."); return name; } public void setName(String name) {
System.out.println("set name..."); this.name = name; }}

我想在setName和getName方法被调用之前打印"before" 之后打印"after", 运行以上main方法成功打印:

before...get name...after ...

cglib代理一共生成了三个class,使用的是asm框架在内存中动态生成的,他们分别是:

CglibDemo$$EnhancerByCGLIB$$1a76a66CglibDemo$$EnhancerByCGLIB$$1a76a66$$FastClassByCGLIB$$ea5d0752CglibDemo$$FastClassByCGLIB$$4320d206

1.先讲解 CglibDemo$$EnhancerByCGLIB$$1a76a66

  • 这个类是我们CglibDemo cglibProxy = (CglibDemo) enhancer.create();获得的代理类,他不是FastClass类
  • 注意他的名字中没有FastClass字眼
  • 因为enhancer.setSuperclass(CglibDemo.class),所以他是CglibDemo的子类,而且名字中也带有CglibDemo字眼
  • 这个类的内容如下:
/** * 这个类是从内存中使用hsdb工具弄下来,再使用idea反编译,然后手动修改其中的编译错误而来的 
* * 这个类是代理类,是cglib生成的CglibDemo子类 */import lombok.SneakyThrows;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;import java.lang.reflect.Method;public class CglibDemo$$EnhancerByCGLIB$$1a76a66 extends CglibDemo implements Factory {
private boolean CGLIB$BOUND; public static Object CGLIB$FACTORY_DATA; private static ThreadLocal CGLIB$THREAD_CALLBACKS; private static Callback[] CGLIB$STATIC_CALLBACKS; private MethodInterceptor CGLIB$CALLBACK_0; private static Object CGLIB$CALLBACK_FILTER; private static Method CGLIB$getName$0$Method; private static MethodProxy CGLIB$getName$0$Proxy; private static Object[] CGLIB$emptyArgs; private static Method CGLIB$setName$1$Method; private static MethodProxy CGLIB$setName$1$Proxy; private static Method CGLIB$equals$2$Method; private static MethodProxy CGLIB$equals$2$Proxy; private static Method CGLIB$toString$3$Method; private static MethodProxy CGLIB$toString$3$Proxy; private static Method CGLIB$hashCode$4$Method; private static MethodProxy CGLIB$hashCode$4$Proxy; private static Method CGLIB$clone$5$Method; private static MethodProxy CGLIB$clone$5$Proxy; public CglibDemo$$EnhancerByCGLIB$$1a76a66() {
CGLIB$BIND_CALLBACKS(this); } static {
CGLIB$STATICHOOK1(); } @SneakyThrows 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); } } @SneakyThrows 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(); } @SneakyThrows 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(); } } @SneakyThrows 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(); } @SneakyThrows public final String getName() {
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$getName$0$Method, CGLIB$emptyArgs, CGLIB$getName$0$Proxy) : super.getName(); } public Object newInstance(Class[] var1, Object[] var2, Callback[] var3) {
CGLIB$SET_THREAD_CALLBACKS(var3); CglibDemo$$EnhancerByCGLIB$$1a76a66 var10000 = new CglibDemo$$EnhancerByCGLIB$$1a76a66(); switch(var1.length) {
case 0: // var10000.
(); CGLIB$SET_THREAD_CALLBACKS((Callback[])null); return var10000; default: throw new IllegalArgumentException("Constructor not found"); } } public Object newInstance(Callback var1) {
CGLIB$SET_THREAD_CALLBACKS(new Callback[]{
var1}); CglibDemo$$EnhancerByCGLIB$$1a76a66 var10000 = new CglibDemo$$EnhancerByCGLIB$$1a76a66(); CGLIB$SET_THREAD_CALLBACKS((Callback[])null); return var10000; } public Object newInstance(Callback[] var1) {
CGLIB$SET_THREAD_CALLBACKS(var1); CglibDemo$$EnhancerByCGLIB$$1a76a66 var10000 = new CglibDemo$$EnhancerByCGLIB$$1a76a66(); CGLIB$SET_THREAD_CALLBACKS((Callback[])null); return var10000; } @SneakyThrows public final void setName(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$setName$1$Method, new Object[]{
var1}, CGLIB$setName$1$Proxy); } else {
super.setName(var1); } } public void setCallbacks(Callback[] var1) {
this.CGLIB$CALLBACK_0 = (MethodInterceptor)var1[0]; } 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 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 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; } public static MethodProxy CGLIB$findMethodProxy(Signature var0) {
String var10000 = var0.toString(); switch(var10000.hashCode()) {
case -1184972270: if (var10000.equals("setName(Ljava/lang/String;)V")) {
return CGLIB$setName$1$Proxy; } break; case -508378822: if (var10000.equals("clone()Ljava/lang/Object;")) {
return CGLIB$clone$5$Proxy; } break; case 1218144844: if (var10000.equals("getName()Ljava/lang/String;")) {
return CGLIB$getName$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; } @SneakyThrows static void CGLIB$STATICHOOK1() {
CGLIB$THREAD_CALLBACKS = new ThreadLocal(); CGLIB$emptyArgs = new Object[0]; Class var0 = Class.forName("hh.proxy.cglib.CglibDemo$$EnhancerByCGLIB$$1a76a66"); 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[]{
"getName", "()Ljava/lang/String;", "setName", "(Ljava/lang/String;)V"}, (var1 = Class.forName("hh.proxy.cglib.CglibDemo")).getDeclaredMethods()); CGLIB$getName$0$Method = var10000[0]; CGLIB$getName$0$Proxy = MethodProxy.create(var1, var0, "()Ljava/lang/String;", "getName", "CGLIB$getName$0"); CGLIB$setName$1$Method = var10000[1]; CGLIB$setName$1$Proxy = MethodProxy.create(var1, var0, "(Ljava/lang/String;)V", "setName", "CGLIB$setName$1"); } private static final void CGLIB$BIND_CALLBACKS(Object var0) {
CglibDemo$$EnhancerByCGLIB$$1a76a66 var1 = (CglibDemo$$EnhancerByCGLIB$$1a76a66)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]; } } final int CGLIB$hashCode$4() {
return super.hashCode(); } final String CGLIB$toString$3() {
return super.toString(); } final String CGLIB$getName$0() {
return super.getName(); } final boolean CGLIB$equals$2(Object var1) {
return super.equals(var1); } final void CGLIB$setName$1(String var1) {
super.setName(var1); } final Object CGLIB$clone$5() throws CloneNotSupportedException {
return super.clone(); }}

2. 类CglibDemo$$FastClassByCGLIB$$4320d206

  • 这个类是一个FastClass类
  • 注意他的名字中FastClass字眼
  • 他是一个FastClass1类, 至于为什么说他是1, 待会解密
  • 这个类的内容如下:
/** * 这个类是从内存中使用hsdb工具弄下来,再使用idea反编译,然后手动修改其中的编译错误而来的 
* * 这个类是一个FastClass,而且他是FastClass1 * @author hh * @date 2020/9/29 */import net.sf.cglib.core.Signature;import net.sf.cglib.reflect.FastClass;import java.lang.reflect.InvocationTargetException;public class CglibDemo$$FastClassByCGLIB$$4320d206 extends FastClass {
public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {
CglibDemo var10000 = (CglibDemo)var2; int var10001 = var1; try {
switch(var10001) {
case 0: CglibDemo.main((String[])var3[0]); return null; case 1: return var10000.getName(); case 2: var10000.setName((String)var3[0]); return null; 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 CglibDemo$$FastClassByCGLIB$$4320d206(Class var1) {
super(var1); } public Object newInstance(int var1, Object[] var2) throws InvocationTargetException {
CglibDemo var10000 = new CglibDemo(); CglibDemo 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 getIndex(Class[] var1) {
switch(var1.length) {
case 0: return 0; default: 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 -75308287: if (var1.equals("getName")) {
switch(var2.length) {
case 0: return 1; } } break; case 3343801: if (var1.equals("main")) {
switch(var2.length) {
case 1: if (var2[0].getName().equals("[Ljava.lang.String;")) {
return 0; } } } break; case 147696667: if (var1.equals("hashCode")) {
switch(var2.length) {
case 0: return 5; } } break; case 1984801293: if (var1.equals("setName")) {
switch(var2.length) {
case 1: if (var2[0].getName().equals("java.lang.String")) {
return 2; } } } } return -1; } public int getIndex(Signature var1) {
String var10000 = var1.toString(); switch(var10000.hashCode()) {
case -1184972270: if (var10000.equals("setName(Ljava/lang/String;)V")) {
return 2; } break; case 1218144844: if (var10000.equals("getName()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 getMaxIndex() {
return 5; }}

3. 类CglibDemo$$EnhancerByCGLIB$$1a76a66$$FastClassByCGLIB$$ea5d0752

  • 这个类是一个的名字有点长, 他是一个FastClass类
  • 注意他的名字中FastClass字眼
  • 他是一个FastClass2类, 至于为什么说他是2, 待会解密
  • 这个类的内容如下:
/** * 这个类是从内存中使用hsdb工具弄下来,再使用idea反编译,然后手动修改其中的编译错误而来的 
* * 这个类是一个FastClass,而且他是FastClass2 * @author hh * @date 2020/9/29 */import net.sf.cglib.core.Signature;import net.sf.cglib.proxy.Callback;import net.sf.cglib.reflect.FastClass;import java.lang.reflect.InvocationTargetException;public class CglibDemo$$EnhancerByCGLIB$$1a76a66$$FastClassByCGLIB$$ea5d0752 extends FastClass {
public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {
CglibDemo$$EnhancerByCGLIB$$1a76a66 var10000 = (CglibDemo$$EnhancerByCGLIB$$1a76a66)var2; int var10001 = var1; try {
switch(var10001) {
case 0: return new Boolean(var10000.equals(var3[0])); case 1: return var10000.toString(); case 2: return new Integer(var10000.hashCode()); case 3: return var10000.clone(); case 4: return var10000.getName(); case 5: return var10000.newInstance((Class[])var3[0], (Object[])var3[1], (Callback[])var3[2]); case 6: return var10000.newInstance((Callback)var3[0]); case 7: return var10000.newInstance((Callback[])var3[0]); case 8: var10000.setName((String)var3[0]); return null; case 9: var10000.setCallbacks((Callback[])var3[0]); return null; case 10: var10000.setCallback(((Number)var3[0]).intValue(), (Callback)var3[1]); return null; case 11: return var10000.getCallbacks(); case 12: return var10000.getCallback(((Number)var3[0]).intValue()); case 13: CglibDemo$$EnhancerByCGLIB$$1a76a66.CGLIB$SET_THREAD_CALLBACKS((Callback[])var3[0]); return null; case 14: CglibDemo$$EnhancerByCGLIB$$1a76a66.CGLIB$SET_STATIC_CALLBACKS((Callback[])var3[0]); return null; case 15: return CglibDemo$$EnhancerByCGLIB$$1a76a66.CGLIB$findMethodProxy((Signature)var3[0]); case 16: CglibDemo$$EnhancerByCGLIB$$1a76a66.CGLIB$STATICHOOK1(); return null; case 17: return new Integer(var10000.CGLIB$hashCode$4()); case 18: return var10000.CGLIB$toString$3(); case 19: return var10000.CGLIB$getName$0(); case 20: return new Boolean(var10000.CGLIB$equals$2(var3[0])); case 21: var10000.CGLIB$setName$1((String)var3[0]); return null; case 22: return var10000.CGLIB$clone$5(); case 23: CglibDemo.main((String[])var3[0]); return null; } } catch (Throwable var4) {
throw new InvocationTargetException(var4); } throw new IllegalArgumentException("Cannot find matching method/constructor"); } public CglibDemo$$EnhancerByCGLIB$$1a76a66$$FastClassByCGLIB$$ea5d0752(Class var1) {
super(var1); } public Object newInstance(int var1, Object[] var2) throws InvocationTargetException {
CglibDemo$$EnhancerByCGLIB$$1a76a66 var10000 = new CglibDemo$$EnhancerByCGLIB$$1a76a66(); CglibDemo$$EnhancerByCGLIB$$1a76a66 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 getIndex(Class[] var1) {
switch(var1.length) {
case 0: return 0; default: return -1; } } public int getIndex(String var1, Class[] var2) {
switch(var1.hashCode()) {
case -1776922004: if (var1.equals("toString")) {
switch(var2.length) {
case 0: return 1; } } break; case -1295482945: if (var1.equals("equals")) {
switch(var2.length) {
case 1: if (var2[0].getName().equals("java.lang.Object")) {
return 0; } } } break; case -1053468136: if (var1.equals("getCallbacks")) {
switch(var2.length) {
case 0: return 11; } } break; case -124978608: if (var1.equals("CGLIB$equals$2")) {
switch(var2.length) {
case 1: if (var2[0].getName().equals("java.lang.Object")) {
return 20; } } } break; case -75308287: if (var1.equals("getName")) {
switch(var2.length) {
case 0: return 4; } } 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 14; } } } break; case -29025554: if (var1.equals("CGLIB$hashCode$4")) {
switch(var2.length) {
case 0: return 17; } } break; case 3343801: if (var1.equals("main")) {
switch(var2.length) {
case 1: if (var2[0].getName().equals("[Ljava.lang.String;")) {
return 23; } } } break; case 5451255: if (var1.equals("CGLIB$setName$1")) {
switch(var2.length) {
case 1: if (var2[0].getName().equals("java.lang.String")) {
return 21; } } } 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 13; } } } break; case 94756189: if (var1.equals("clone")) {
switch(var2.length) {
case 0: return 3; } } break; case 147696667: if (var1.equals("hashCode")) {
switch(var2.length) {
case 0: return 2; } } break; case 161998109: if (var1.equals("CGLIB$STATICHOOK1")) {
switch(var2.length) {
case 0: return 16; } } break; case 220068330: if (var1.equals("CGLIB$getName$0")) {
switch(var2.length) {
case 0: return 19; } } break; case 495524492: if (var1.equals("setCallbacks")) {
switch(var2.length) {
case 1: if (var2[0].getName().equals("[Lnet.sf.cglib.proxy.Callback;")) {
return 9; } } } break; case 1154623345: if (var1.equals("CGLIB$findMethodProxy")) {
switch(var2.length) {
case 1: if (var2[0].getName().equals("net.sf.cglib.core.Signature")) {
return 15; } } } break; case 1543336190: if (var1.equals("CGLIB$toString$3")) {
switch(var2.length) {
case 0: return 18; } } 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 6; } break; case 1730110032: if (var10001.equals("[Lnet.sf.cglib.proxy.Callback;")) {
return 7; } } 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 5; } } } 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 10; } } } break; case 1905679803: if (var1.equals("getCallback")) {
switch(var2.length) {
case 1: if (var2[0].getName().equals("int")) {
return 12; } } } break; case 1951977611: if (var1.equals("CGLIB$clone$5")) {
switch(var2.length) {
case 0: return 22; } } break; case 1984801293: if (var1.equals("setName")) {
switch(var2.length) {
case 1: if (var2[0].getName().equals("java.lang.String")) {
return 8; } } } } return -1; } 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 13; } break; case -1457535688: if (var10000.equals("CGLIB$STATICHOOK1()V")) {
return 16; } break; case -1411812934: if (var10000.equals("CGLIB$hashCode$4()I")) {
return 17; } break; case -1184972270: if (var10000.equals("setName(Ljava/lang/String;)V")) {
return 8; } break; case -894172689: if (var10000.equals("newInstance(Lnet/sf/cglib/proxy/Callback;)Ljava/lang/Object;")) {
return 6; } break; case -623122092: if (var10000.equals("CGLIB$findMethodProxy(Lnet/sf/cglib/core/Signature;)Lnet/sf/cglib/proxy/MethodProxy;")) {
return 15; } break; case -508378822: if (var10000.equals("clone()Ljava/lang/Object;")) {
return 3; } break; case -419626537: if (var10000.equals("setCallbacks([Lnet/sf/cglib/proxy/Callback;)V")) {
return 9; } break; case 374345669: if (var10000.equals("CGLIB$equals$2(Ljava/lang/Object;)Z")) {
return 20; } break; case 453440181: if (var10000.equals("CGLIB$getName$0()Ljava/lang/String;")) {
return 19; } break; case 560567118: if (var10000.equals("setCallback(ILnet/sf/cglib/proxy/Callback;)V")) {
return 10; } break; case 811063227: if (var10000.equals("newInstance([Ljava/lang/Class;[Ljava/lang/Object;[Lnet/sf/cglib/proxy/Callback;)Ljava/lang/Object;")) {
return 5; } break; case 973717575: if (var10000.equals("getCallbacks()[Lnet/sf/cglib/proxy/Callback;")) {
return 11; } break; case 1218144844: if (var10000.equals("getName()Ljava/lang/String;")) {
return 4; } break; case 1221173700: if (var10000.equals("newInstance([Lnet/sf/cglib/proxy/Callback;)Ljava/lang/Object;")) {
return 7; } break; case 1230699260: if (var10000.equals("getCallback(I)Lnet/sf/cglib/proxy/Callback;")) {
return 12; } 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 18; } break; case 1584330438: if (var10000.equals("CGLIB$SET_STATIC_CALLBACKS([Lnet/sf/cglib/proxy/Callback;)V")) {
return 14; } break; case 1826985398: if (var10000.equals("equals(Ljava/lang/Object;)Z")) {
return 0; } break; case 1913648695: if (var10000.equals("toString()Ljava/lang/String;")) {
return 1; } break; case 1984935277: if (var10000.equals("hashCode()I")) {
return 2; } break; case 2011844968: if (var10000.equals("CGLIB$clone$5()Ljava/lang/Object;")) {
return 22; } break; case 2033562728: if (var10000.equals("CGLIB$setName$1(Ljava/lang/String;)V")) {
return 21; } } return -1; } public int getMaxIndex() {
return 23; }}

Cglib代理生成的所有类都介绍了,下面介绍cglibProxy.getName();都做了什么

注意这个getName我希望他之前打印before,之后打印after,所以他是一个代理方法,被我增强了

CglibDemo cglibProxy = (CglibDemo) enhancer.create(); 得到的是 CglibDemo$$EnhancerByCGLIB$$1a76a66(类名没有FastClass哦),我调用的是getName()方法,那么这个代理类一定也有getName()方法:

@SneakyThrows    public final String getName() {
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$getName$0$Method, CGLIB$emptyArgs, CGLIB$getName$0$Proxy) : super.getName(); }

他实际调用的是拦截器的intercept方法,拦截器就是:

enhancer.setCallback(new MethodInterceptor() {
@Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("before..."); Object result = proxy.invokeSuper(obj, args); System.out.println("after ..."); return result; } });

好吧我们把它贴到一起做一个对比

var10000.intercept(this,          CGLIB$getName$0$Method,    CGLIB$emptyArgs,     CGLIB$getName$0$Proxy) @Override public Object intercept(Object obj,    Method method,             Object[] args,       MethodProxy proxy) throws Throwable {
}

然后到了拦截器的intercept方法,我调用了proxy.invokeSuper(obj, args);

到这里, 就必须说说之前我为什么说一个FastClass是1,另一个FastClass是2, 看invokeSuper源码:

public Object invokeSuper(Object obj, Object[] args) throws Throwable {
try {
init(); FastClassInfo fci = fastClassInfo; return fci.f2.invoke(fci.i2, obj, args); } catch (InvocationTargetException e) {
throw e.getTargetException(); } }

其中, FastClassInfo就包含了两个FastClass, 他的两个属性,f1=CglibDemo$$FastClassByCGLIB$$4320d206f2=CglibDemo$$EnhancerByCGLIB$$1a76a66$$FastClassByCGLIB$$ea5d0752

所以, invokeSuper他用的是FastClass2,也就是f2, (invoke使用的是FastClass1也就是f1), Object参数还是代理对象啊, 当然还有一个属性,fci.i2, 这个i2就是index2的意思,就是方法索引, 这个方法索引什么意思呢, 继续往下看. 现在调用的是FastClass2的invoke,我们看看这个invoke里面写的是啥:

public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {
CglibDemo$$EnhancerByCGLIB$$1a76a66 var10000 = (CglibDemo$$EnhancerByCGLIB$$1a76a66)var2; int var10001 = var1; try {
switch(var10001) {
case 0: return new Boolean(var10000.equals(var3[0])); case 1: return var10000.toString(); case 2: return new Integer(var10000.hashCode()); case 3: return var10000.clone(); case 4: return var10000.getName(); case 5: return var10000.newInstance((Class[])var3[0], (Object[])var3[1], (Callback[])var3[2]); case 6: return var10000.newInstance((Callback)var3[0]); case 7: return var10000.newInstance((Callback[])var3[0]); case 8: var10000.setName((String)var3[0]); return null; case 9: var10000.setCallbacks((Callback[])var3[0]); return null; case 10: var10000.setCallback(((Number)var3[0]).intValue(), (Callback)var3[1]); return null; case 11: return var10000.getCallbacks(); case 12: return var10000.getCallback(((Number)var3[0]).intValue()); case 13: CglibDemo$$EnhancerByCGLIB$$1a76a66.CGLIB$SET_THREAD_CALLBACKS((Callback[])var3[0]); return null; case 14: CglibDemo$$EnhancerByCGLIB$$1a76a66.CGLIB$SET_STATIC_CALLBACKS((Callback[])var3[0]); return null; case 15: return CglibDemo$$EnhancerByCGLIB$$1a76a66.CGLIB$findMethodProxy((Signature)var3[0]); case 16: CglibDemo$$EnhancerByCGLIB$$1a76a66.CGLIB$STATICHOOK1(); return null; case 17: return new Integer(var10000.CGLIB$hashCode$4()); case 18: return var10000.CGLIB$toString$3(); case 19: return var10000.CGLIB$getName$0(); case 20: return new Boolean(var10000.CGLIB$equals$2(var3[0])); case 21: var10000.CGLIB$setName$1((String)var3[0]); return null; case 22: return var10000.CGLIB$clone$5(); case 23: CglibDemo.main((String[])var3[0]); return null; } } catch (Throwable var4) {
throw new InvocationTargetException(var4); } throw new IllegalArgumentException("Cannot find matching method/constructor"); }

这里就是根据方法索引去找方法, 很显然我调用的是getName,那么这个case语句有两个getName:

case 4:       return var10000.getName();case 19:      return var10000.CGLIB$getName$0();

var10000是代理对象啊(切记), 所以这里不会调用var10000.getName() 因为如果调用的是这个,那么就无限循环调用代理的getName方法了, 好,我们看看代理对象CglibDemo$$EnhancerByCGLIB$$1a76a66CGLIB$getName$0方法:

final String CGLIB$getName$0() {
return super.getName(); }

前面介绍了,代理对象是CglibDemo的子类,这里的super就是CglibDemo,所以到这里就调用了CglibDemo的getName方法了:

public String getName() {
System.out.println("get name..."); return name; }

到这里, 主体流程讲完了,现在讲下有些细节

一个方法在代理对象的构造

private static Method CGLIB$getName$0$Method; private static MethodProxy CGLIB$getName$0$Proxy;  public final String getName() {
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$getName$0$Method, CGLIB$emptyArgs, CGLIB$getName$0$Proxy) : super.getName(); }final String CGLIB$getName$0() {
return super.getName();}

每个方法,都有这么些东西:

  • Method CGLIB$getName$0$Method 反射的原生方法
  • MethodProxy CGLIB$getName$0$Proxy 增强方法,这个方法涉及到FastClass,和方法的索引,方法的索引其实是根据方法的name和参数type的HashCode生成的, 将他的HashCode分配一个int的索引值,比如1,2或者其他数字,比如:
public int getIndex(Signature var1) {
String var10000 = var1.toString(); switch(var10000.hashCode()) {
case 453440181: if (var10000.equals("CGLIB$getName$0()Ljava/lang/String;")) {
return 19; } break; case 1218144844: if (var10000.equals("getName()Ljava/lang/String;")) {
return 4; } break;

其中Signature就是根据方法名和参数类型调用toString方法生成的, 方法的hashCode和方法的index是早就对应好了的,因为这些FastClass和代理class都是调用asm生成的,生成的时候,这些就已经对应好了

现在讲解一下FastClass1,也就是如果我在拦截器调用proxy.invoke(obj, args); 会发生啥

invoke的源码:

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; } }

跟invokeSuper的唯一区别就是, invoke使用的是fci.f1也就是FastClass1, 就是CglibDemo$$FastClassByCGLIB$$4320d206

invokeSuper使用的是fci.f2也就是FastClass2,也就是CglibDemo$$EnhancerByCGLIB$$1a76a66$$FastClassByCGLIB$$ea5d0752

那么,FastClass1.invoke发生了啥? ,贴上FastClass1的invoke源码:

public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {
CglibDemo var10000 = (CglibDemo)var2; int var10001 = var1; try {
switch(var10001) {
case 0: CglibDemo.main((String[])var3[0]); return null; case 1: return var10000.getName(); case 2: var10000.setName((String)var3[0]); return null; 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"); }

好吧,调用的是var10000.getName(); 调用的还是代理类的getName,所以又循环调用了,注意注意 CglibDemo var10000 = (CglibDemo)var2; 他不是真的CglibDemo,而是一个代理类, 是CglibDemo$$EnhancerByCGLIB$$1a76a66 extends CglibDemo

好了到这里已经讲解完毕cglib的原理, 以下是问答:

  • 源码是使用hsdb从内存直接dump的,也可以System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, “c:\classes”);生成. 这里不介绍这个,以后有时间介绍
  • 不可以debug,因为字节码的行号,和反编译的行号对应不上,因为使用的是asm生成的所以行号乱了,不过debug下还是可以看到FastClass的静态字段
  • 他的调用方式区别与jdk动态代理,使用的是方法签名的HashCode去case when找到具体方法,所以不是反射,效率会比反射高一点(经过测试,不是特别明显)
  • 每个方法都会生成一个MethodProxy, 里面fastClass是一样的,但是方法索引是不同的

最后串一遍流程

proxy.getName() —>intercept.invoke(…)—>methodProxy.invokeSuper()—>fastClass.f2.invoke()—>经过case when找到var10000.CGLIB$getName 0 ( ) − − − − > 然 后 又 到 了 p r o x y , 调 用 C G L I B 0() ----> 然后又到了proxy,调用CGLIB 0()>proxyCGLIBgetName$0----> super.getName() 完毕

转载地址:https://blog.csdn.net/qq_31543867/article/details/108876715 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:spark之卡方特征选择(ChiSqSelector)
下一篇:G1GC(garbage first)

发表评论

最新留言

网站不错 人气很旺了 加油
[***.192.178.218]2024年04月21日 04时35分02秒