Spring 源碼分析(三) —— AOP(一)AOP原理

AOP概論

        AOP(Aspect-Oriented Programming,面向切面的編程),談起AOP,則必定會追溯到OOP(Object Oriented Programming,面向對象編程),由於AOP能夠說是對OOP的補充和完善,而這一切的理念都是從模塊化開始的。OOP是一種很是成功、極具表現力的編程範式,它將概念天然地表達爲對象,從而將其中通用的代碼模塊化。因此,衡量OOP成功與否的標準就是它在多大程度上避免了代碼的重複。通常狀況下,OOP可以很好地避免代碼重複。具體繼承能夠幫助咱們在不一樣類型之間共享相同的行爲;多態讓咱們能夠用一樣的方式來處理不一樣類型之間的對象,可以讓咱們將注意力集中在他們的共同之處。但當趕上一些特定問題的時候,好比,當咱們須要爲分散的對象引入公共行爲時,OOP就顯得很無力了。也就是說,OOP很適合你定義從上到下的關係,但不適合定義水平的關係。能夠說由於有這些Bug的存在,是AOP生成的直接誘因,因此是爲了彌補OOP而存在的。AOP在看待應用程序結構的方式上與OOP是大相徑庭的,以AOP的思路來看,系統是被分解成方面(Aspect)或者關注點(Concern),而不是一個個對象。追根溯源,與OOP同樣,AOP只不過是一種全新的模塊化機制而已,他的主要做用是用來描述分散在對象、類或函數中的橫切關注點,從關注點中分離出橫切關注點則是 AOP的核心概念。正則表達式

        AOP的原理,也是很是簡單的,即經過分離關注點讓解決特定領域問題的代碼從業務邏輯中獨立出來,業務邏輯的代碼中就再也不含有針對特定領域問題代碼的調用,業務邏輯同特定領域問題的關係則經過切面來封裝、維護,這樣本來分散在整個應用程序中的代碼就能夠很好的進行管理了。例如:在使用公共函數的時候,每每須要進行一些邏輯設計,也就時須要代碼實現來支持,而這些邏輯代碼也是須要維護的,在傳統的公共子模塊的調用中,除了直接調用之外就沒有其餘的手段。而相同的狀況,在使用AOP後,不只能夠將這些重複的代碼抽出來單獨維護,並且能夠在須要時進行統一調度,這樣的使用方法雖然與設計公共子模塊有幾分類似,但他爲這一類問題的解決提供了一整套完整的理論和靈活多樣的實現方法。也就是說,在AOP提出橫切概念之後,再把模塊功能正交化的同時,也在此基礎上提供了一系列橫切的靈活實現。編程

        

AOP體系

       實現原理

         在編譯期修改源代碼、運行期節碼加載前修改字節碼或字節碼加載後動態建立代理類的節碼,這是AOP的具體實現方法,而他是由三個重要步驟來完成的,先是生成代理對象,而後是攔截器的做用,最後是編織的具體實現。AOP框架的豐富,其實很大程度上體如今這三個步驟上所具備的豐富技術選擇,以及與IOC容器之間的無縫縫合。而若是以實現方法來分的話,則主要有兩類:靜態AOP(包括靜態織入)和動態AOP(包含動態代理、動態節碼生成、自定義類加載器、節碼轉換器)。
緩存


       結構概述

        除了經過使用Proxy代理對象、攔截器字節碼翻譯技術等一系列已有的AOP或者AOP實現技術,來實現切面應用的各類編織實現和環繞加強之外。還成立了AOP聯盟來探索AOP的標準化,但願藉此來推進AOP的發展。而對於如今已有的AOP實現方案,AOP聯盟對它們進行了必定程度的抽象,從而定義出了AOP的體系結構。結合這個AOP體系結構去了解AOP技術是很是有幫助的,AOP聯盟定義的AOP體系結構如圖所示:性能優化

        AOP聯盟定義的AOP體系結構把與AOP相關的概念大體分爲由高到低、從使用到實現的三個層次。從上往下:框架

        最高層是語言和開發環境,在這個環境中能夠看到幾個重要的概念:「基礎」能夠視爲待加強對象或者說目標對象;「切面」一般包含對於基礎的加強應用;「配置」能夠當作是一種編織,經過在AOP體系中提供這個配置環境,能夠把基礎和切面結合起來,從而完成切面對目標對象的編織實現。
模塊化

        AOP體系結構的第二層次爲語言和開發環境提供支持的,在這個層次中能夠看到AOP框架的高層實現,主要包括配置和編織實現兩部份內容。例如配置邏輯和編織邏輯實現自己,以及對這些實現進行抽象的一些高層API封裝。這些實現和API封裝,爲前面提到的語言和開發環境的實現提供了有力的支持。
函數

        最底層是編織的具體實現模塊,各類技術均可以做爲編織邏輯的具體實現方法,好比反射、程序預處理、攔截器框架、類裝載器框架、元數據處理等等。性能


       使用概況

        AOP在 權限(Authentication)、緩存(Cache)、內容傳遞(Context passing)、錯誤處理(Error handling)、懶加載(Lazy loading)、調試(Debug)、日誌(Log)、跟蹤優化和校準(tracing、profiling and monitoring)、性能優化(Performance optimization)、持久化(Persistence)、資源池(Resource pooling)、同步(Synchronization)、事務(Transactions)等方面都有用處,能夠說是可以使用範圍及廣。下面咱們就以一張思惟導圖來串聯,以此來鋪開與AOP相關的全部的知識點。優化

                AOP一般包含如下相關術語:
spa

                        一、目標對象(Target):包含鏈接點的對象。也被用來引用加強化或代理化對象。

                        二、代理(Proxy):AOP 框架建立的對象,包含加強。

                        三、鏈接點(Joinpoint):程序執行過程當中明確的點,如方法的調用或特定的異常被拋出。

                        四、切點(Pointcut):指定一個通知將被引起的一系列鏈接點。AOP 框架必須容許開發者指定切入點:例如,使用正則表達式。

                        五、加強(Advice):在特定的鏈接點AOP框架執行的動做。各類類型的加強包括「around」、「before」、「throws」加強等等。加強類型將在下面討論。許多 AOP 框架都是以攔截器作加強模型,維護一個「圍繞」鏈接點的攔截器鏈。

                        六、切面(Advisor):一個關注點的模塊化,這個關注點實現可能另外橫切多個對象。事物管理是J2EE應用中橫切關注點中一個很好的例子。切面通常是用 Advisor 或者 攔截器實現。

                        七、織入(Weaving):組裝方面建立通知化對象。這能夠在編譯時完成(例如:使用AspectJ編譯器),也能夠在運行時完成。Spring 和其餘一些純 Java AOP 框架,使用運行時織入。

                        八、引入(Introduction):添加方法或字段到加強化類。

                        九、接口(IsModified):用於簡化緩存。(這裏做爲補充)。


                AOP加強類型(也叫 通知類型)包括:

                        一、Before Advice(前置加強):在一個鏈接點以前執行的加強,但這個加強不能阻止流程繼續執行到鏈接點(除非它拋出一個異常)。

                        二、After Advice(後加強,全稱是 After returning advice 正常返回加強 ):在鏈接點正常完成後執行的加強,例如,若是一個正常返回,沒有拋出異常。若是拋出異常則不會執行。

                        三、Around Advice(環繞加強):包圍一個鏈接點的加強,如方法調用,是最強大的加強。在方法調用先後完成自定義的行爲。它們負責選擇繼續執行鏈接點或直接返回它們本身的返回值或拋出異常來執行。

                        四、Throws Advice(拋出加強,全稱是 After throwing advice 異常返回加強,也叫 Finally returning advice 最終返回加強是最經常使用的加強類型。大部分是基於攔截器框架如Nanning或者JBoss4提供的Around加強。做用是,無論,是否正常執行,都會返回加強中的內容。

                        五、Introduction Advice(引入加強):一種很是特殊的加強。它將新的成員變量、成員方法引入到目標類中。它僅能做用於類層次,而不是方法層次,因此他不能做用於任何切入點。


‍‍Spring AOP 實現原理

        AOP模塊是Spring的核心模塊,儘管Spring中有本身的一套AOP實現,但在Java社區中是最完整AOP框架仍是Aspectj,因此爲了彌補本身的不足,也爲了提供更加豐富的AOP解決方案,Spring對Aspectj作了集成。同時,再配合Spring的IOC容器,Spring推出了一個完善的AOP解決方法。

        Spring AOP的核心技術是JDK的動態代理技術。Spring AOP是以動態代理技術爲基礎,設計出了一系列AOP的橫切實現,好比:前置加強、返回加強、異常加強等等。同時,Spring AOP還提供了一系列的Pointcut來匹配切入點,可使用現有的切入點來設計橫切面,也能夠擴展相關的Pointcut方法來切入需求。

        Spring AOP 中,咱們通常是經過配置文件或者編程的方式來實現的。常見的配置方法有四種:1,配置 ProxyFactoryBean 顯示設置 advisors、advice、target 等。2,配置 AutoProxyCreator 這種方式下,仍是如之前同樣定義 bean,可是從容器中得到的實際上是代理對象。3,配置 <aop:config>。4,配置 <aop:aspectj-autoproxy>,使用 AspectJ 的註解來表示以前以及切入點。而編程方式是直接經過 ProxyFactory 設置 target 對象,再經過 getProxy 方法來獲取代理對象。 

         總的來講,在Spring AOP中,對於AOP的使用者來講,可能簡單配置 Bean 便可,但仔細分析 Spring AOP 的內部設計就能夠看到,爲了讓AOP起做用,須要參照前面的 AOP 實現原理來完成一系列過程,須要爲目標對象創建代理對象,這個代理對象能夠經過使用JDK的Proxy來完成,也能夠經過第三方的類生成器CGLIB來完成。而後,還須要啓動代理對象的攔截器來完成各類橫切面的織入,這一系列的織入設計時經過一系列 Adapter 來實現的。經過一系列 Adapter 的設計,就能夠把AOP的橫切面設計和Proxy模式有機地結合起來,從而實如今 AOP 中定義各類織入方式(這裏的源碼部分可能不會涉及)。具體實現過程筆者會在後面的文章中詳細闡述。



——水門(2016年3月於杭州

相關文章
相關標籤/搜索