1、靜態AOP:在編譯期,切面直接以字節 碼的形式編譯到目標字節 碼文件中。
AspectJ屬於靜態AOP,是在編譯時進行增強,會在編譯的時候將AOP邏輯織入到代碼中,需要專有的編譯器和織入器。
- 優點:被織入的類性能不受影響。
- 缺點:不夠靈活
2、動態AOP(JDK動態代理):在運行期,目標類加載后,為接口動態生成代理類,將切面植入到代理類中。
Java從1.3引入動態代理。實現原理是為被代理的業務接口生成代理類,將AOP邏輯寫入到代理類中,在運行時動態織入AOP,使用反射執行織入的邏輯。
主要實現方式依賴java.lang.reflect包下的InvocationHandler和Proxy類。
- 優點:Java標准庫原生支持,使用簡單,無需引用額外的包。相對於靜態AOP更靈活。
- 缺點:帶代理的類必須是接口,靈活性受到一些限制;使用反射會影響一些性能。
3、動態代碼字節生成:在運行期,目標類加載后,動態構建字節碼文件生成目標類的子類,將切面邏輯加入到子類中。
CGLib是動態代碼字節生成的實現,它封裝字節碼生成工具Asm,原理是在運行期間目標字節碼加載后,生成目標類的子類,將切面邏輯加入到子類中,所以使用Cglib實現AOP不需要基於接口。
- 優點:沒有接口也可以織入,靈活性高。
- 缺點:擴展類的實例方法為final時,則無法進行織入
4、自定義類加載器:在運行前,目標加載前,將切面邏輯加到目標字節碼中。
可以考慮javassist來實現。Javassist 是一個編輯字節碼的框架,可以讓你很簡單地操作字節碼。它可以在運行期定義或修改Class。使用Javassist實現AOP的原理是在字節碼加載前直接修改需要切入的方法。
- 優點:可以對絕大部分類織入。
- 缺點:如果用到了其他類加載器,則這些類將不被織入