上一篇從Web開發演進過程的一個側面簡述了一下爲何會有Spring?事實上只介紹了爲何會有Spring IOC(控制反轉/依賴注入)以及Spring IOC的雛形。咱們知道Spring的兩個核心知識點是:IOC和AOP。所以,這一篇仍是以Web開發演進過程爲線索繼續探討一下爲何會有Spring AOP?等介紹完這兩個核心的知識點以後,纔會進一步展開對Spring核心原理的探討!數據庫
咱們在初學習Java Web的時候,應該都經歷瞭如下的階段:編程
(1)一個主函數main中包含了全部的方法;
(2)將主函數中的方法進行拆分封裝,抽取爲一個個的方法;
(3)按照每個方法不一樣的功能分爲一個個的類;
(4)有了MVC模型以後,咱們按照MVC的思想將咱們的代碼拆分爲三層,每層負責不一樣的功能,進行分門別類的管理;設計模式
不少程序的功能還能夠經過繼承關係而獲得重用,進一步提升了開發效率。再後來,又出現了各類各樣的設計模式,使設計程序功能變得駕輕就熟。app
在面向對象的大環境下,咱們能夠很好地組織代碼,經過繼承、封裝和多態的思想去設計一個個比較讓人滿意的類,可是咱們慢慢的發現,咱們的代碼中逐漸多了不少重複性的代碼,有人可能會想到,把這些重複性的代碼抽取出來不就行了嗎?是這樣的,咱們看一下這種思路的一個實例:框架
能夠看到,上述代碼功能上確實能夠實現,可是咱們的業務代碼已經被這些非核心的代碼所混淆,而且佔據了大量的空間!顯然這種顯示的調用過程成爲了咱們開發過程當中的一個痛點,如何將相似這種的非核心的代碼剝離出去成爲一個迫切須要解決的問題!函數式編程
不只如此,假設咱們要控制每個方法的訪問權限,只容許一部分用戶進行訪問,在不考慮過濾器的狀況下,咱們是否是須要在每個方法開始的時候判斷用戶是否具備該權限,若是有的話就能夠進行訪問,若是沒有的話,就不容許進行訪問!函數
諸如此類,還有數據庫事務的控制,數據庫鏈接的建立和關閉等等,這些都充斥這大量重複性的模板代碼!一個很現實的問題,假若有一天,業務需求不須要進行日誌記錄了,那豈不是咱們須要把之前寫的代碼,所有刪掉!想一想都是一件很可怕的事情!學習
若是你對設計模式玩的比較熟的話,這個時候你可能會想到使用JDK動態代理設計模式(動態代理設計模式能夠在原有的方法先後添加判斷、選擇或其餘邏輯)對上述代碼進行改進,(關於什麼是JDK動態代理,這裏再也不詳細贅述,有不懂的的能夠查閱相關資料具體瞭解一下!)修改後的代碼以下:測試
上述爲代理類,紅色框中圈出的表示之前業務中的模板代碼,這裏直接輸出表示方法執行的過程,之前的UserServiceImpl修改成以下(直接用輸出的方式表示方法執行了):spa
測試代碼以下:
上述的執行結果能夠看出,每次調用一個方法的時候先後都會調用咱們指望的代碼,實現了咱們指望的標準!
經過JDK動態代理的方式,讓咱們完全的解放出來了!
上述過程當中,咱們看到在動態代理的invoke
方法裏邊,咱們至關於在原有方法的調用先後「植入」了咱們的通用日誌記錄代碼,若是你看到這一層的話,那麼恭喜你!你已經領悟到了AOP思想最核心的東西了!
上述抽取公共代碼其實就是AOP中橫切的過程,代理對象中在方法調用先後「植入」本身寫的通用日誌記錄代碼其實就是AOP中織入的過程!這個織入的代碼也就是橫切邏輯,織入代碼的過程其實就是在原有的方法先後加強 原方法的過程!總的來講,咱們想解決咱們開發中的痛點,而後就出現了一種技術,這種技術手段就是AOP。
AOP書面表述以下:
AOP(Aspect Oriented Programming)意爲:面向切面編程,經過預編譯方式和運行期動態代理實現程序功能的統一維護的一種技術。AOP是OOP的延續,是軟件開發中的一個熱點,也是Spring框架中的一個重要內容(Spring核心之一),是函數式編程的一種衍生範型。利用AOP能夠對業務邏輯的各個部分進行隔離,從而使得業務邏輯各部分之間的耦合度下降,提升程序的可重用性,同時提升了開發的效率。
AOP是一種思想,不一樣的廠商或企業可能有不一樣的實現方式,爲了更好的應用AOP技術,技術專家們成立了AOP聯盟來探討AOP的標準化,AOP聯盟定義的AOP體系結構把與AOP相關的概念大體分爲由高到低、從使用到實現的三層關係,AOP聯盟定義的AOP體系結構以下圖:
在AOP聯盟定義的AOP體系結構下有不少的實現者,例如:AspectJ、AspectWerkz、JBoss AOP、Spring AOP等。Spring AOP就是在此標準下產生的,這裏再也不深刻Spring AOP的其餘概念,這些概念會在後期探討。
上述經過動態代理的方式實現了簡單的AOP,可是值得注意的是,咱們的代理目標對象必須實現一個接口,要是一個接口的實現類,這是由於再生成Proxy對象的時候這個方法須要一個目標對象的接口:
顯然,有些特殊的場景使用JDK動態代理技術的話,已經不可以知足咱們的場景了,又遇到痛點了!凡事不勞咱們操心的Spring框架已經替咱們想到了,既然你有這種需求,我就使用一種技術幫你實現就好了,Spring在這裏使用CGLib動態代理的方式實現了咱們的這種訴求。
CGLib採用底層的字節碼技術,能夠爲一個類建立子類,在子類中採用方法攔截的技術攔截全部父類方法的調用並順勢的織入橫切邏輯。
看到這裏,咱們會想之後會不會還有CGLib解決不了得問題啊?咱們已經很清楚的知道了對於Spring AOP來講,使用到了JDK動態代理技術和CGLib動態代理技術,這兩種方式已經實現了咱們絕大多數的場景,若是還有不能知足的需求,迫切須要解決的痛點,我相信Spring還會採用相應的技術來知足這些場景。
上述的過程,大體從一個側面探討了一下咱們爲何須要AOP,AOP與Spring AOP的關係以及Spring AOP兩種實現的方式(JDK動態代理和CGLib動態代理)。
Spring不嘗試提供最爲完善的AOP實現,它更側重於提供一種和Spring IOC容器整個的AOP實現,用於解決實際的問題,在Spring中無縫的整合了Spring AOP、Spring IOC和AspectJ。
固然,Spring AOP的內容不只僅有這些!例如:咱們在使用Spring AOP的時候只是簡單的配置了一下(經過XML或註解進行配置),沒有像ProxyDemo
測試類中的那樣,還須要咱們手動的調用ProxyFactory
來建立代理對象,而後調用咱們的目標方法,其實Spring AOP在內部已經幫咱們把這些事情作好了,具體的原理後期會繼續探討。另外,Spring如何整合Spring IOC和AOP的,這一點也會在後期探討。
最後補充一下!動態代理或者設計模式重要嗎?很重要!Spring AOP用到了動態代理,Spring事務管理用到了動態代理,MyBatis數據庫鏈接池用到了動態代理,MyBatis建立Mapper用到了動態代理等等,你說重要不!要想踏進這些高層框架原理的大門,設計模式首先是咱們的第一段臺階!