1. 程式人生 > >Spring-AOP的原理-動態代理-IOC-註解配置

Spring-AOP的原理-動態代理-IOC-註解配置

一:概念的介紹:

    什麼叫AOP?

          關鍵:  橫向重複,縱向提取;

        AOP能為容器中管理的物件動態生成代理物件,AOP是指程式設計不是針對某一個物件,而是針對一群物件,打個比方:就像一個一個個圓柱形,這一個個圓柱形就是一個個物件,OOP思想就是往這個圓柱裡面填充方法,屬性等等,但是AOP的思想就是,把這個圓柱切開,把一些通用的東西加進去,常見的如 日誌,事件等等。AOP是一種思想,並一定要用動態代理的方式來實現,想過濾器,攔截器等都是AOP的思想;

    連線點:目標物件中,所有可以被增強的方法叫做連線點;

    切入點:已經被增強的方法叫做切點:

    通知/增強:增強的內容(程式碼),有前置通知,環繞通知,後置通知,異常通知等,常見的如:事務,日誌等;

    目標物件:被代理物件;

    織入:就是把通知和連線點連線,形成切點的過程;

    代理:將通知織入目標物件之後形成代理物件;

    切面:切入點加通知就叫切面;

二:AOP的實現原理:

    AOP有兩種實現方式:動態代理和CGlib代理;

    動態代理:動態代理需要的條件就是需要目標物件實現的介面,如果沒有介面的話就不能使用動態代理模式;則只能使用    CGlib(Code Generation Library)代理模式;也是Spring預設代理方式;

     CGlib代理模式:是通過繼承的方式,形成目標物件的子類,對子類進行增強,從而形成代理,所有當父類被final修飾的時候,那麼這個時候就不能使用CGlib代理了;

    補充:無論是動態代理還是CGlib代理,要實現的目的就是為了能夠在程式設計的時候,完成宣告式程式設計--就是我通過宣告就可以得到我想要的物件,不需要再對考慮某個類的資訊在進行修改。就是AOP的思想。他想要實現能在執行的過程中,動態的修改物件的資訊,但是JVM是不支援這麼做的,於是引進了一項技術----ASM,這個ASM就是能夠在虛擬機器中動態的修改位元組碼中資訊,動態的修改已生成的class,而且可以動態的生成新的Class,    CGlib代理其實就是這個ASM對上層封裝。從而才能構成了代理,動態代理生成的是“兄弟”,CGlib代理生成的是“孩子”

。還有一個就是CGlib代理技術對原類 方法進行訪問的時候不不是使用的是反射技術,而是FastClass技術,所以CGlib技術一般生成物件的時候,比較慢,但是執行的時候比較快。而動態代理就是生產的是一個新的類,這個類和被代理的類繼承同一個介面,新生成的類中加入要新增的方法,這個新生成的類作為真實物件的代理來處理事情,就是動態代理。

動態代理讓代理類和目標類實現同一個介面,cglib生成一個目標類的子類。mybatis用的動態代理,spring兩種都用,以前經常會使用介面bean,號稱動態代理比cglib穩定,但動態代理效能遠不如cglib。

三:IOC(Inverse Of Control)反轉控制

    簡而言之,就是將建立物件的權利反轉了,我們以前的物件都是自己建立的,包括依賴關係也是自己注入的,但是有了Spring之後,物件的建立以及依賴的注入都可以由Spring來完成了。

    但是Spring建立物件的時候,那些物件所依賴的資訊怎麼來呢?比如:我要建立一個Tom這個人,這個人的姓名是Tom,年齡是18,那麼我就要告訴Spring這些資訊,這就引入了另一個概念:依賴注入(DI  Dependency Injection)

    依賴注入的方式:

                構造器;

                set方法;

                欄位注入;

    注入的型別:值型別和引用型別;

四:註解配置

    註解的通俗解釋:註解,可以理解成一種元資料,也就是對資料進行描述的資料,比如說,當虛擬機器看到一個方法的時候,如果上面有@Override ,虛擬機器就知道他是他父類或者介面的重寫了,這裡的註解也是為了這個意思,當虛擬機器看到註解的時候,就能知道這個方法的作用,從而生成你想要的相應功能。他可以節省xml繁瑣的配置。

    Resource和autowired的區別:

    Resource是javax.annotation.Resource 下面的類,並不是Spring裡面的註解;他的預設是使用ByName自動注入的;

    autowried則是Spring自帶的註解;預設使用的是ByType型別注入的,預設情況下要求依賴的物件必須是存在的,如果允許為null,可以設定他的required為false;

    兩者都可以對欄位和set方法進行注入;