Spring框架入門必備教程-AOP面向切面編程(上篇)

AOP為Aspect Oriented Programming的縮寫,意為:面向切面編程,通過預(yù)編譯方式和運行期間動態(tài)代理實現(xiàn)程序功能的統(tǒng)一維護的一種技術(shù)。
AOP是OOP的延續(xù),是軟件開發(fā)中的一個熱點,也是Spring框架中的一個重要內(nèi)容,是函數(shù)式編程的一種衍生范型。
利用AOP可以對業(yè)務(wù)邏輯的各個部分進行隔離,從而使得業(yè)務(wù)邏輯各部分之間的耦合度降低,提高程序的可重用性,同時提高了開發(fā)的效率。
AOP?面向切面編程
不使用 AOP?的開發(fā)方式
Step1:項目 aop_leadin1
先定義好接口與一個實現(xiàn)類,該實現(xiàn)類中除了要實現(xiàn)接口中的方法外,還要再寫兩個非業(yè)務(wù)方法。非業(yè)務(wù)方法也稱為交叉業(yè)務(wù)邏輯:
doTransaction():用于事務(wù)處理
doLog():用于日志處理
然后,再使接口方法調(diào)用它們。接口方法也稱為主業(yè)務(wù)邏輯。接口:


Step2:項目 aop_leadin2
當然,也可以有另一種解決方案:將這些交叉業(yè)務(wù)邏輯代碼放到專門的工具類或處理類中,由主業(yè)務(wù)邏輯調(diào)用。


AOP?簡介
AOP(Aspect Orient Programming),面向切面編程。面向切面編程是從動態(tài)角度考慮程序運行過程。
AOP 為Aspect Oriented Programming 的縮寫,意為:面向切面編程,可通過運行期動態(tài)代理實現(xiàn)程序功能的統(tǒng)一維護的一種技術(shù)。AOP 是Spring 框架中的一個重要內(nèi)容。利用AOP 可以對業(yè)務(wù)邏輯的各個部分進行隔離,從而使得業(yè)務(wù)邏輯各部分之間的耦合度降低,提高程序的可重用性, 同時提高了開發(fā)的效率。
面向切面編程,就是將交叉業(yè)務(wù)邏輯封裝成切面,利用AOP 容器的功能將切面織入到主業(yè)務(wù)邏輯中。所謂交叉業(yè)務(wù)邏輯是指,通用的、與主業(yè)務(wù)邏輯無關(guān)的代碼,如安全檢查、事務(wù)、日志、緩存等。
若不使用AOP,則會出現(xiàn)代碼糾纏,即交叉業(yè)務(wù)邏輯與主業(yè)務(wù)邏輯混合在一起。這樣,會使主業(yè)務(wù)邏輯變的混雜不清。
例如,轉(zhuǎn)賬,在真正轉(zhuǎn)賬業(yè)務(wù)邏輯前后,需要權(quán)限控制、日志記錄、加載事務(wù)、結(jié)束事務(wù)等交叉業(yè)務(wù)邏輯,而這些業(yè)務(wù)邏輯與主業(yè)務(wù)邏輯間并無直接關(guān)系。但,它們的代碼量所占比重能達到總代碼量的一半甚至還多。它們的存 在,不僅產(chǎn)生了大量的“冗余”代碼,還大大干擾了主業(yè)務(wù)邏輯---轉(zhuǎn)賬。
面向切面編程對有什么好處?
1.?減少重復(fù);
2.?專注業(yè)務(wù);
注意:面向切面編程只是面向?qū)ο缶幊痰囊环N補充。
使用AOP 減少重復(fù)代碼,專注業(yè)務(wù)實現(xiàn):

AOP?編程術(shù)語
(1)?切面(Aspect)
切面泛指交叉業(yè)務(wù)邏輯。上例中的事務(wù)處理、日志處理就可以理解為切面。常用的切面是通知(Advice)。實際就是對主業(yè)務(wù)邏輯的一種增強。
(2)?連接點(JoinPoint)
連接點指可以被切面織入的具體方法。通常業(yè)務(wù)接口中的方法均為連接點。
(3)?切入點(Pointcut)
切入點指聲明的一個或多個連接點的集合。通過切入點指定一組方法。
被標記為final 的方法是不能作為連接點與切入點的。因為最終的是不能被修改的,不能被增強的。
(4)?目標對象(Target)
目標對象指將要被增強的對象。即包含主業(yè)務(wù)邏輯的類的對象。上例中的StudentServiceImpl 的對象若被增強,則該類稱為目標類,該類對象稱為目標對象。當然,不被增強,也就無所謂目標不目標了。
(5)?通知(Advice)
通知表示切面的執(zhí)行時間,Advice 也叫增強。上例中的MyInvocationHandler 就可以理解為是一種通知。換個角度來說,通知定義了增強代碼切入到目標代碼的時間點,是目標方法執(zhí)行之前執(zhí)行,還是之后執(zhí)行等。通知類型不同,切入時間不同。
切入點定義切入的位置,通知定義切入的時間。
?
AspectJ?對 AOP?的實現(xiàn)
對于AOP 這種編程思想,很多框架都進行了實現(xiàn)。Spring 就是其中之一,可以完成面向切面編程。然而,AspectJ也實現(xiàn)了AOP的功能,且其實現(xiàn)方式更為簡捷,使用更為方便,而且還支持注解式開發(fā)。所以,Spring 又將AspectJ 的對于 AOP 的實現(xiàn)也引入到了自己的框架中。
在 Spring 中使用 AOP 開發(fā)時,一般使用AspectJ 的實現(xiàn)方式。
?
AspectJ 簡介
AspectJ 是一個優(yōu)秀面向切面的框架,它擴展了Java 語言,提供了強大的切面實現(xiàn)。
官網(wǎng)地址:http://www.eclipse.org/aspectj/?
AspetJ 是Eclipse 的開源項目,官網(wǎng)介紹如下:

a seamless aspect-oriented extension to the Javatm programming language(一種基于Java 平臺的面向切面編程的語言)
Java platform compatible(兼容Java 平臺,可以無縫擴展) easy to learn and use(易學(xué)易用)
AspectJ?的通知類型
AspectJ 中常用的通知有五種類型:
(1)?前置通知
(2)?后置通知
(3)?環(huán)繞通知
(4)?異常通知
(5)?最終通知
AspectJ?的切入點表達式
AspectJ 定義了專門的表達式用于指定切入點。表達式的原型是:

解釋:
modifiers-pattern]?訪問權(quán)限類型
ret-type-pattern?返回值類型
declaring-type-pattern 包名類名
name-pattern(param-pattern)?方法名(參數(shù)類型和參數(shù)個數(shù))?
throws-pattern 拋出異常類型
?表示可選的部分
以上表達式共 4 個部分:
execution(訪問權(quán)限 方法返回值 方法聲明(參數(shù)) 異常類型)
切入點表達式要匹配的對象就是目標方法的方法名。所以,execution?表達式中明顯就是方法的簽名。注意,表達式中黑色文字表示可省略部分,各部分間用空格分開。
在其中可以使用以下符號:

舉 例 :?
execution(public * *(..))
指定切入點為:任意公共方法。execution(* set*(..))
指定切入點為:任何一個以“set”開始的方法。execution(* com.xyz.service.*.*(..))
指定切入點為:定義在service 包里的任意類的任意方法。execution(* com.xyz.service..*.*(..))
指定切入點為:定義在service 包或者子包里的任意類的任意方法。“..”出現(xiàn)在類名中時,后面必須跟“*”,表示包、子包下的所有類。
execution(* *..service.*.*(..))
指定所有包下的serivce 子包下所有類(接口)中所有方法為切入點
execution(* *.service.*.*(..))
指定只有一級包下的serivce 子包下所有類(接口)中所有方法為切入點
execution(* *.ISomeService.*(..))
指定只有一級包下的ISomeSerivce 接口中所有方法為切入點
execution(* *..ISomeService.*(..))
指定所有包下的ISomeSerivce 接口中所有方法為切入點
execution(* com.xyz.service.IAccountService.*(..))?
指定切入點為:IAccountService?接口中的任意方法。
execution(*?com.xyz.service.IAccountService+.*(..))
指定切入點為:IAccountService 若為接口,則為接口中的任意方法及其所有實現(xiàn)類中的任意方法;若為類,則為該類及其子類中的任意方法。execution(* joke(String,int)))
指定切入點為:所有的joke(String,int)方法,且joke()方法的第一個參數(shù)是String,第二個參數(shù)是int。如果方法中的參數(shù)類型是java.lang 包下的類,可以直接使用類名,否則必須使用全限定類名,如joke( java.util.List, int)。execution(* joke(String,*)))
指定切入點為:所有的joke()方法,該方法第一個參數(shù)為String,第二個參數(shù)可以是任意類型,如joke(String s1,String s2)和joke(String s1,double d2) 都是,但joke(String s1,double d2,String s3)不是。
execution(* joke(String,..)))
指定切入點為:所有的joke()方法,該方法第一個參數(shù)為String,后面可以有任意個參數(shù)且參數(shù)類型不限,如joke(String s1)、joke(String s1,String s2)和joke(String s1,double d2,String s3)都是。
execution(* joke(Object))
指定切入點為:所有的joke()方法,方法擁有一個參數(shù),且參數(shù)是Object 類型。joke(Object ob)是,但,joke(String s)與joke(User u)均不是。execution(* joke(Object+)))
指定切入點為:所有的joke()方法,方法擁有一個參數(shù),且參數(shù)是Object 類型或該類的子類。不僅joke(Object ob)是,joke(String s)和joke(User u)也是。
AspectJ?的開發(fā)環(huán)境
(1)?maven?依賴

(2)?引入 AOP?約束
在AspectJ?實現(xiàn)AOP?時,要引入 AOP 的約束。配置文件中使用的AOP 約束中的標簽,均是AspectJ?框架使用的,而非 Spring?框架本身在實現(xiàn) AOP 時使用的。
AspectJ 對于 AOP 的實現(xiàn)有注解和配置文件兩種方式,常用是注解方式。
?
最后奉上視頻教程??,視頻觀看效果更佳?。∽哌^路過別忘素質(zhì)三連哦~~

