代码拉取完成,页面将自动刷新
本项目旨在从AOP生成的class文件入手,完全搞懂AOP(以常规的cglib为基础)。
对于AOP一直的观点都是AOP是动态修改class字节码, 但到底生成了什么样的代码, 仍然是雾里看花, 让我们保存动态生成的class文件到磁盘一探究竟.
运行ProxyFactoryTest的Junit,即可看到生成的class文件(通过两种方式生成,生成的内容一致)
文件一:org.smvc.test.aop.TableDao$$EnhancerByCGLIB$$b6871ed4.class
文件二:gen.class/.....
/// Before表示拦截器栈(不需要关注如何实现的)
@Before(value={LogInterceptor.class, AuthInterceptor.class})
public class TableDao {
public void create(){
System.out.println("create() is running...");
}
public void delete(){
System.out.println("delete() is running...");
}
public void update(){
System.out.println("update() is running...");
}
@Clear(value=AuthInterceptor.class)
public void query(){
System.out.println("query() is running...");
}
}
方法1.(ProxyFactory.java)利用cglib的增强API 即可获得class的字节码, 通过文件流保存即可(保存在工程根目录:org.smvc.test.aop.TableDao$$EnhancerByCGLIB$$b6871ed4.class).
byte[] bytes = Enhancer.getStrategy().generate(en)
方法2. (ProxyFactoryTest.java)利用cglib提供的保存生成的字节码参数(保存在gen.class目录下):
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "gen.class");
生成的class文件不一定能通过一般的反编译工具打开(反编译成功的可能不准确),原因未知, 但是我们可以通过eclipse的class字节码解析工具,获得如下结果(重点关注其中一个void create方法,删除一些干扰项):
// Compiled from <generated> (version 1.2 : 46.0, no super bit)
/// **类继承自TableDao,即代理类,这就是为什么能强转为代理类直接使用的原因**
public class org.smvc.test.aop.TableDao$$EnhancerByCGLIB$$d519990f extends org.smvc.test.aop.TableDao implements net.sf.cglib.proxy.Factory {
// Field descriptor #9 Z
private boolean CGLIB$BOUND;
// Field descriptor #11 Ljava/lang/ThreadLocal;
private static final java.lang.ThreadLocal CGLIB$THREAD_CALLBACKS;
// Field descriptor #13 [Lnet/sf/cglib/proxy/Callback;
private static final net.sf.cglib.proxy.Callback[] CGLIB$STATIC_CALLBACKS;
// **这里就是我们通过Enhance设定进去的拦截器栈**
// Field descriptor #15 Lnet/sf/cglib/proxy/MethodInterceptor;
private net.sf.cglib.proxy.MethodInterceptor CGLIB$CALLBACK_0;
// Field descriptor #26 Ljava/lang/reflect/Method;
private static final java.lang.reflect.Method CGLIB$create$0$Method;
// Field descriptor #28 Lnet/sf/cglib/proxy/MethodProxy;
private static final net.sf.cglib.proxy.MethodProxy CGLIB$create$0$Proxy;
// Method descriptor #17 ()V
// Stack: 1, Locals: 1
final void CGLIB$create$0();
0 aload_0 [this]
1 invokespecial org.smvc.test.aop.TableDao.create() : void [34]
4 return
// Method descriptor #17 ()V
// Stack: 5, Locals: 1
/// 代理类的create方法
public final void create();
0 aload_0 [this]
/// **先获取拦截器栈**
1 getfield org.smvc.test.aop.TableDao$$EnhancerByCGLIB$$d519990f.CGLIB$CALLBACK_0 : net.sf.cglib.proxy.MethodInterceptor [36]
4 dup
/// **如果拦截器栈不为空**
5 ifnonnull 17
8 pop
9 aload_0 [this]
10 invokestatic org.smvc.test.aop.TableDao$$EnhancerByCGLIB$$d519990f.CGLIB$BIND_CALLBACKS(java.lang.Object) : void [40]
13 aload_0 [this]
/// **绑定参数,准备调用拦截器栈**
14 getfield org.smvc.test.aop.TableDao$$EnhancerByCGLIB$$d519990f.CGLIB$CALLBACK_0 : net.sf.cglib.proxy.MethodInterceptor [36]
17 dup
18 ifnull 37
21 aload_0 [this]
22 getstatic org.smvc.test.aop.TableDao$$EnhancerByCGLIB$$d519990f.CGLIB$create$0$Method : java.lang.reflect.Method [42]
25 getstatic org.smvc.test.aop.TableDao$$EnhancerByCGLIB$$d519990f.CGLIB$emptyArgs : java.lang.Object[] [44]
28 getstatic org.smvc.test.aop.TableDao$$EnhancerByCGLIB$$d519990f.CGLIB$create$0$Proxy : net.sf.cglib.proxy.MethodProxy [46]
/// **准备好参数,正好能和Callback类的intercept方法四个参数对应上,调用拦截器栈**
31 invokeinterface net.sf.cglib.proxy.MethodInterceptor.intercept(java.lang.Object, java.lang.reflect.Method, java.lang.Object[], net.sf.cglib.proxy.MethodProxy) : java.lang.Object [52] [nargs: 5]
36 return
/// **否则拦截器栈为空,则直接调用被代理类的真实方法**
37 aload_0 [this]
38 invokespecial org.smvc.test.aop.TableDao.create() : void [34]
41 return
// Method descriptor #231 ([Lnet/sf/cglib/proxy/Callback;)V
// Stack: 1, Locals: 1
public static void CGLIB$SET_STATIC_CALLBACKS(net.sf.cglib.proxy.Callback[] arg0);
0 aload_0 [arg0]
1 putstatic org.smvc.test.aop.TableDao$$EnhancerByCGLIB$$d519990f.CGLIB$STATIC_CALLBACKS : net.sf.cglib.proxy.Callback[] [237]
4 return
// Method descriptor #38 (Ljava/lang/Object;)V
// Stack: 3, Locals: 2
private static final void CGLIB$BIND_CALLBACKS(java.lang.Object arg0);
0 aload_0 [arg0]
1 checkcast org.smvc.test.aop.TableDao$$EnhancerByCGLIB$$d519990f [2]
4 astore_1
5 aload_1
6 getfield org.smvc.test.aop.TableDao$$EnhancerByCGLIB$$d519990f.CGLIB$BOUND : boolean [239]
9 ifne 52
12 aload_1
13 iconst_1
14 putfield org.smvc.test.aop.TableDao$$EnhancerByCGLIB$$d519990f.CGLIB$BOUND : boolean [239]
17 getstatic org.smvc.test.aop.TableDao$$EnhancerByCGLIB$$d519990f.CGLIB$THREAD_CALLBACKS : java.lang.ThreadLocal [24]
20 invokevirtual java.lang.ThreadLocal.get() : java.lang.Object [242]
23 dup
24 ifnonnull 39
27 pop
28 getstatic org.smvc.test.aop.TableDao$$EnhancerByCGLIB$$d519990f.CGLIB$STATIC_CALLBACKS : net.sf.cglib.proxy.Callback[] [237]
31 dup
32 ifnonnull 39
35 pop
36 goto 52
39 checkcast net.sf.cglib.proxy.Callback[] [243]
42 aload_1
43 swap
44 iconst_0
45 aaload
46 checkcast net.sf.cglib.proxy.MethodInterceptor [48]
49 putfield org.smvc.test.aop.TableDao$$EnhancerByCGLIB$$d519990f.CGLIB$CALLBACK_0 : net.sf.cglib.proxy.MethodInterceptor [36]
52 return
// Method descriptor #245 ([Lnet/sf/cglib/proxy/Callback;)Ljava/lang/Object;
// Stack: 2, Locals: 2
public java.lang.Object newInstance(net.sf.cglib.proxy.Callback[] arg0);
0 aload_1 [arg0]
1 invokestatic org.smvc.test.aop.TableDao$$EnhancerByCGLIB$$d519990f.CGLIB$SET_THREAD_CALLBACKS(net.sf.cglib.proxy.Callback[]) : void [247]
4 new org.smvc.test.aop.TableDao$$EnhancerByCGLIB$$d519990f [2]
7 dup
8 invokespecial org.smvc.test.aop.TableDao$$EnhancerByCGLIB$$d519990f() [248]
11 aconst_null
12 invokestatic org.smvc.test.aop.TableDao$$EnhancerByCGLIB$$d519990f.CGLIB$SET_THREAD_CALLBACKS(net.sf.cglib.proxy.Callback[]) : void [247]
15 areturn
// Method descriptor #249 (Lnet/sf/cglib/proxy/Callback;)Ljava/lang/Object;
// Stack: 4, Locals: 2
public java.lang.Object newInstance(net.sf.cglib.proxy.Callback arg0);
0 iconst_1
1 anewarray net.sf.cglib.proxy.Callback [251]
4 dup
5 iconst_0
6 aload_1 [arg0]
7 aastore
8 invokestatic org.smvc.test.aop.TableDao$$EnhancerByCGLIB$$d519990f.CGLIB$SET_THREAD_CALLBACKS(net.sf.cglib.proxy.Callback[]) : void [247]
11 new org.smvc.test.aop.TableDao$$EnhancerByCGLIB$$d519990f [2]
14 dup
15 invokespecial org.smvc.test.aop.TableDao$$EnhancerByCGLIB$$d519990f() [248]
18 aconst_null
19 invokestatic org.smvc.test.aop.TableDao$$EnhancerByCGLIB$$d519990f.CGLIB$SET_THREAD_CALLBACKS(net.sf.cglib.proxy.Callback[]) : void [247]
22 areturn
// Method descriptor #252 ([Ljava/lang/Class;[Ljava/lang/Object;[Lnet/sf/cglib/proxy/Callback;)Ljava/lang/Object;
// Stack: 5, Locals: 4
public java.lang.Object newInstance(java.lang.Class[] arg0, java.lang.Object[] arg1, net.sf.cglib.proxy.Callback[] arg2);
0 aload_3 [arg2]
1 invokestatic org.smvc.test.aop.TableDao$$EnhancerByCGLIB$$d519990f.CGLIB$SET_THREAD_CALLBACKS(net.sf.cglib.proxy.Callback[]) : void [247]
4 new org.smvc.test.aop.TableDao$$EnhancerByCGLIB$$d519990f [2]
7 dup
8 aload_1 [arg0]
9 dup
10 arraylength
11 tableswitch default: 35
case 0: 28
28 pop
29 invokespecial org.smvc.test.aop.TableDao$$EnhancerByCGLIB$$d519990f() [248]
32 goto 50
35 goto 38
38 pop
39 new java.lang.IllegalArgumentException [254]
42 dup
43 ldc_w <String "Constructor not found"> [256]
46 invokespecial java.lang.IllegalArgumentException(java.lang.String) [259]
49 athrow
50 aconst_null
51 invokestatic org.smvc.test.aop.TableDao$$EnhancerByCGLIB$$d519990f.CGLIB$SET_THREAD_CALLBACKS(net.sf.cglib.proxy.Callback[]) : void [247]
54 areturn
// Method descriptor #261 (I)Lnet/sf/cglib/proxy/Callback;
// Stack: 2, Locals: 2
public net.sf.cglib.proxy.Callback getCallback(int arg0);
0 aload_0 [this]
1 invokestatic org.smvc.test.aop.TableDao$$EnhancerByCGLIB$$d519990f.CGLIB$BIND_CALLBACKS(java.lang.Object) : void [40]
4 aload_0 [this]
5 iload_1 [arg0]
6 tableswitch default: 30
case 0: 24
24 getfield org.smvc.test.aop.TableDao$$EnhancerByCGLIB$$d519990f.CGLIB$CALLBACK_0 : net.sf.cglib.proxy.MethodInterceptor [36]
27 goto 32
30 pop
31 aconst_null
32 areturn
// Method descriptor #263 (ILnet/sf/cglib/proxy/Callback;)V
// Stack: 2, Locals: 3
public void setCallback(int arg0, net.sf.cglib.proxy.Callback arg1);
0 iload_1 [arg0]
1 tableswitch default: 31
case 0: 20
20 aload_0 [this]
21 aload_2 [arg1]
22 checkcast net.sf.cglib.proxy.MethodInterceptor [48]
25 putfield org.smvc.test.aop.TableDao$$EnhancerByCGLIB$$d519990f.CGLIB$CALLBACK_0 : net.sf.cglib.proxy.MethodInterceptor [36]
28 goto 31
31 return
// Method descriptor #265 ()[Lnet/sf/cglib/proxy/Callback;
// Stack: 5, Locals: 1
public net.sf.cglib.proxy.Callback[] getCallbacks();
0 aload_0 [this]
1 invokestatic org.smvc.test.aop.TableDao$$EnhancerByCGLIB$$d519990f.CGLIB$BIND_CALLBACKS(java.lang.Object) : void [40]
4 aload_0 [this]
5 iconst_1
6 anewarray net.sf.cglib.proxy.Callback [251]
9 dup
10 iconst_0
11 aload_0 [this]
12 getfield org.smvc.test.aop.TableDao$$EnhancerByCGLIB$$d519990f.CGLIB$CALLBACK_0 : net.sf.cglib.proxy.MethodInterceptor [36]
15 aastore
16 areturn
// Method descriptor #231 ([Lnet/sf/cglib/proxy/Callback;)V
// Stack: 5, Locals: 2
public void setCallbacks(net.sf.cglib.proxy.Callback[] arg0);
0 aload_0 [this]
1 aload_1 [arg0]
2 dup2
3 iconst_0
4 aaload
5 checkcast net.sf.cglib.proxy.MethodInterceptor [48]
8 putfield org.smvc.test.aop.TableDao$$EnhancerByCGLIB$$d519990f.CGLIB$CALLBACK_0 : net.sf.cglib.proxy.MethodInterceptor [36]
11 return
// Method descriptor #17 ()V
// Stack: 0, Locals: 0
static {};
0 invokestatic org.smvc.test.aop.TableDao$$EnhancerByCGLIB$$d519990f.CGLIB$STATICHOOK2() : void [269]
3 return
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。