天天看點

Spring-AOP的原理-動态代理-IOC-注解配置

一:概念的介紹:

    什麼叫AOP?

Spring-AOP的原理-動态代理-IOC-注解配置

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

        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方法進行注入;