你真的懂AOP嗎?

1 AOP概念
spring

AOP(Aspect Oriented Programming) 面向切面編程,是OOP(Object Oriented Programming,面向對象編程)的補充和完善。AOP技術利用一種稱爲"橫切"的技術,剖解開封裝的對象內部,並將那些影響了多個類的公共行爲封裝到一個可重用模塊,即切面。所謂"切面"可減小系統的重複代碼,下降模塊之間的耦合度 ,並有利於將來的可操做性和可維護性。橫切關注點常常發生在覈心關注點的多處,且各處基本類似,好比權限認證、日誌、事物。編程


2 代理設計模式設計模式

要想明白aop實現原理,必定要掌握代理模式,其中代理模式的定義:給某一個對象提供一個代理,並由代理對象控制對原對象的引用。下面是代理模式的簡單類圖與調用過程。bash


3 代理實現技術
app

Java編程中的實現代理模式分爲靜態代理、動態代理兩種,靜態也就是在程序運行前就已經存在代理類的字節碼文件,代理類和委託類的關係在運行前就肯定了,而動態代理是在實現階段不用關心代理類,而在運行階段才指定哪個對象,這就須要代碼具有能動態建立一個類的能力。首先,咱們先溫習下Java從編譯到運行的整個過程,編譯Java文件以後產生.class 文件在磁盤中, JVM虛擬機讀取字節碼文件,取出二進制數據加載到內存中,解析.class 文件內的信息,生成對應的 Class對象,而後再實例化的過程的例子。那麼,若是咱們在運行期系統中遵循Java1編譯系統組織.class文件的格式和結構,生成相應的二進制數據,而後再把這個二進制數據加載轉換成對應的類,這樣就具備了在代碼中動態建立一個類的能力。

採用JDK自帶的Proxy類方法,其基本流程爲:主函數-->代理-->目標對象。對於Proxy類(被代理類)有一個使用前提:目標對象必需要實現接口,利用Proxy實現AOP的主要步驟以下:建立接口->建立接口實現類->建立代理工廠類。經過查看生成的代理類的字節碼文件能夠看到,生成的代理類是繼承了Proxy主類和實現了指定的Dao接口,在初始化的時候將會加載被代理類的方法生成Method對象,Proxy父類中保存了實際處理的invoke方法, 因此外部調用代理類定義的方法時,Method元數據與方法參數都將會轉發到方法代理類的定義好的invoke方法中。
// 1.首先實現一個InvocationHandler,方法調用會被轉發到該類的invoke()方法
public class DaoInvocationHandler implements InvocationHandler {
    @Override
    public Object invoke(Object proxy, Method method, Object[] args)  {
       return method.invoke(object, args);
    }
}
//2.而後在須要使用Dao的時候,經過JDK動態代理獲取Dao的代理對象
System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true"); //開啓debug模式,保存動態生成的代理類字節碼文件
Dao dao = new DaoImpl();
Dao proxyDao = (Dao) Proxy.newProxyInstance(
getClass().getClassLoader(),// 1. 類加載器
        new Class[]{Dao.class}, // 2. 代理須要實現的接口,能夠有多個
        new DaoInvocationHandler(dao));// 3. 方法調用的實際處理者
複製代碼



Cglib(Code Generation Library)是一個優秀的動態代理框架,是一個強大的,高性能的,高質量的Code生成類庫,能夠在運行期擴展Java類與實現Java接口。它的底層使用ASM在內存中動態的生成被代理類的子類,使用CGLIB即便代理類沒有實現任何接口也能夠實現動態代理功能。CGLIB具備簡單易用的特色,它的運行速度要遠遠快於JDK的Proxy動態代理。asm.jar–CGLIB的底層實現,cglib.jar – CGLIB的核心jar包。CGLIB的核心類:
net.sf.cglib.proxy.Enhancer–主要的加強類
net.sf.cglib.proxy.MethodIntercepto –主要的方法攔截類,它是Callback接口的子接口,須要用戶實現
net.sf.cglib.proxy.MethodProxy–JDK的Java.lang.reflect.Method類的代理類,能夠方便的實現對源對象方法的調用;
實現AOP功能步驟以下所示:引入相關jar文件->建立實體類->建立CGLib代理類->建立入口類進行測試。
// 1. 首先實現一個MethodInterceptor,方法調用會被轉發到該類的intercept()方法。
class DaoMethodInterceptor implements MethodInterceptor{
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy).{
        return proxy.invokeSuper(obj, args);
    }
}
// 2. 而後在須要使用HelloConcrete的時候,經過CGLIB動態代理獲取代理對象。
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "./$DaoProxy.class");
Enhancer enhancer = new Enhancer(); //1.新建代理加強對象
enhancer.setSuperclass(DaoImpl.class); //2.設置被代理類
enhancer.setCallback(new DaoMethodInterceptor());  //3.插入方法攔截對象
Dao dao = (DaoImpl)enhancer.create(); //4.獲取被代理對象
複製代碼

經過查看生成的代理類的字節碼文件能夠看到,cglib生成了三個類,有興趣的能夠自行了解一下cglib的機制。生成的代理類是經過繼承被代理類實現的,因此須要指定父類。在初始化的時候也同樣會加載被代理類的方法生成Method對象,因此外部調用代理類定義方法時,會先去執行攔截方法而後纔是真正的被代理類的方法。框架

4.總結
ide

本篇介紹了AOP的概念,代理的設計模式與實現技術,使用了jdk proxy與cglib的接口用來作些簡單的代理實現並分析了原理,格物而致知,積小步而致千里。函數

下一期咱們將模擬spring-aop的實現,手擼個小型的aop框架出來。敬請期待!性能






相關文章
相關標籤/搜索