AOP(Aspect Oriented Programming),即面向切面編程,能夠說是OOP(Object Oriented Programming,面向對象編程)的補充和完善。OOP引入封裝、繼承、多態等概念來創建一種對象層次結構,用於模擬公共行爲的一個集合。不過OOP容許開發者定義縱向的關係,但並不適合定義橫向的關係,例如日誌功能。日誌代碼每每橫向地散佈在全部對象層次中,而與它對應的對象的核心功能毫無關係對於其餘類型的代碼,如安全性、異常處理和透明的持續性也都是如此,這種散佈在各處的無關的代碼被稱爲橫切(cross cutting),在OOP設計中,它致使了大量代碼的重複,而不利於各個模塊的重用。spring
AOP技術偏偏相反,它利用一種稱爲"橫切"的技術,剖解開封裝的對象內部,並將那些影響了多個類的公共行爲封裝到一個可重用模塊,並將其命名爲"Aspect",即切面。所謂"切面",簡單說就是那些與業務無關,卻爲業務模塊所共同調用的邏輯或責任封裝起來,便於減小系統的重複代碼,下降模塊之間的耦合度,並有利於將來的可操做性和可維護性。編程
使用"橫切"技術,AOP把軟件系統分爲兩個部分:核心關注點和橫切關注點。業務處理的主要流程是核心關注點,與之關係不大的部分是橫切關注點。橫切關注點的一個特色是,他們常常發生在覈心關注點的多處,而各處基本類似,好比權限認證、日誌、事物。AOP的做用在於分離系統中的各類關注點,將核心關注點和橫切關注點分離開來。安全
Advice定義在鏈接點作什麼,爲切面加強提供織入接口。它主要描述Spring AOP圍繞方法調用而注入的切面行爲。spa
加強(advice)主要包括以下五種類型
1. 前置加強(BeforeAdvice):在目標方法執行前實施加強
2. 後置加強(AfterReturningAdvice):在目標方法執行後實施加強
3. 環繞加強(MrthodInterceptor):在目標方法執行先後實施加強
4. 異常拋出加強(ThrowsAdvice):在目標方法拋出異常後實施加強
5. 引介加強(IntroductionIntercrptor):在目標類中添加一些新的方法和屬性設計
Pointcut(切點)決定Advice通知應該做用於哪一個鏈接點。代理
完成對目標方法的切面加強設計(Advice)和關注點的設計(Pointcut)之後,須要一個對象把它們結合在一塊,完成這個做用的就是Advisor(通知器)。Advisor定義應該使用哪一個通知並在哪一個關注點使用它,將Advice注入程序中Pointcut位置。日誌
經過配置和調用spring的ProxyFactoryBean來完成代理對象的生成,可使用JDK的Proxy和CGLIB兩種方式生成。對象
ProxyFactoryBean是一個FactoryBean, 用來配置目標對象和切面行爲。在ProxyFactoryBean中, 經過interceptorNames屬性來配置已經定義好的通知器Advisor, 還須要爲target目標對象生成Proxy代理對象,從而爲AOP橫切面編制好準備工做。繼承
在FactoryBean中獲取對象, 是以getObject()方法做爲入口完成的,也是經過該方法對target目標對象進行加強處理來爲AOP功能的實現提供服務。getObject方法首先對通知鏈進行初始化,通知鏈封裝了一系列攔截器,這些攔截器都在配置中讀取。接口
Spring AOP經過JDK的Proxy方式或CGLIB方式生成代理對象的時候,相關的攔截器已經配置到代理對象中去了,攔截器在代理對象中起做用是經過對這些方法的回調來完成的。
JDK的 Proxy來生成代理對象,須要經過Invocationhandler來設置攔截器回調;CGLIB生成代理對象,經過DynamicAdvisedInterceptor來完成回調。
invoke方法是JDK Proxy代理對象進行攔截回調的入口。invoke方法包含了一個完整的攔截鏈對目標對象的攔截過程,好比得到攔截器鏈並對攔截器鏈中的攔截器進行配送,逐個運行攔截器鏈中的攔截加強,直到最後對目標對象方法的運行等。
Cglib2AopProxy回調是在DynamicAdvisedInterceptor對象中實現,回調的實如今intercept方法中。實現相似上邊的invoke方法。
AOP目標對象的加強封裝在AOP攔截器鏈中,由一個個具體的攔截器來完成。兩種代理對象對攔截器鏈的調用都是在ReflectiveMethodInvocation中經過proceed方法實現。在proceed方法中,先進行判斷,若是已經運行到攔截器鏈的末尾,就直接調用目標方法的實現方法;不然沿着攔截器鏈, 獲得下一個攔截器,經過這個攔截器進行matches判斷是否適用於橫切加強的集合,若是是,從攔截器中獲得通知器,並啓動通知器的invoke方法進行切面加強,這個過程會迭代調用proceed方法。
advisor通知器的取得是委託給IOC容器完成的。ProxyFactoryBean經過回調容器的getBean去獲取配置在Bean定義文件中的通知器。ProxyFactoryBean給出通知器的名字, 這些名字配置在interceptorNames的List中配置好。在IOC對FactoryBean進行依賴注入時,會直接注入到FactoryBean的interceptorNames的屬性中。完成這個過程,ProxyFactoryBean就得到了配置的通知器,爲未完成切面加強作好了準備。