Spring AOP怎么用?相信很多人對Spring AOP使用方法的了解處于一知半解狀態(tài),小編給大家總結(jié)了以下內(nèi)容。如下資料是關(guān)于Spring AOP使用方法的內(nèi)容。
10年積累的成都網(wǎng)站制作、網(wǎng)站設(shè)計(jì)經(jīng)驗(yàn),可以快速應(yīng)對客戶對網(wǎng)站的新想法和需求。提供各種問題對應(yīng)的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡(luò)服務(wù)。我雖然不認(rèn)識你,你也不認(rèn)識我。但先網(wǎng)站設(shè)計(jì)后付款的網(wǎng)站建設(shè)流程,更有尼木免費(fèi)網(wǎng)站建設(shè)讓你可以放心的選擇與我們合作。
Java在面向?qū)ο蟮氖澜缋餆o限風(fēng)光,oop成就了無數(shù)經(jīng)典的軟件,它讓我們的軟件更健壯,更易于維護(hù),但是程序猿對軟件的質(zhì)量追求是永無止境的,oop對于業(yè)務(wù)的抽象和封裝完美的無懈可擊
然而對于系統(tǒng)層面的一些需求比如系統(tǒng)日志,性能統(tǒng)計(jì)等,分散在軟件的各個(gè)角落,維護(hù)起來很是不爽,這種問題的解決確是oop力所不能及的,于是AOP橫空出世
先來看一個(gè)簡單的小例子,體會一下AOP能解決什么問題:
如果我們要在A,B,C三個(gè)類的do方法中都加入日志功能
定義一個(gè)日志類Record,加日志的方法:addRecord
Public class A{
Public void do(){
…
Record.addRecord();//添加日志
}
}
Public class B{
Public void do(){
…
Record.addRecord();//添加日志
}
}
Public class C{
Public void do(){
…
Record.addRecord();//添加日志
}
}
這樣做可以解決問題,但是總感覺有些別扭,每個(gè)類的do方法中都調(diào)用了添加日志的方法,添加日志的方法不是我們的核心業(yè)務(wù),我們卻要去處理它
隨著系統(tǒng)越來越完善,類似這樣的非核心業(yè)務(wù)也會越來越多,比如權(quán)限,異常處理,性能監(jiān)控等
這樣的功能出現(xiàn)在很多類的很多方法中干擾了我們的核心業(yè)務(wù)代碼,怎么解決呢?AOP就是為此而生:
看看AOP是如何解決的?
從上圖可以看出對于日志記錄,性能監(jiān)控,異常處理這樣的非核心功能,單獨(dú)被抽取出來,與業(yè)務(wù)代碼分離,橫切在核心業(yè)務(wù)代碼之上
這就是我們通常所說的面向切面編程(AOP),通過一個(gè)例子看看他是如何實(shí)現(xiàn)的
創(chuàng)建一個(gè)UserDao類:
@Repository
public classUserDao {
public voidaddUser(){
System.out.println("添加用戶");
}
public voidupdateUser(){
System.out.println("修改用戶");
}
public voiddeleteUser(){
System.out.println("刪除用戶");
}
}
創(chuàng)建一個(gè)切面類:
@Aspect
public classMyAspectLog {
/**
*方法執(zhí)行完后執(zhí)行的方法
*/
@After(value="execution(* cn.xh.dao.UserDao.addUser(..))")
public voidlog(){
System.out.println("記錄日志");
}
}
在spring配置文件中加入:
當(dāng)我們創(chuàng)建UserDao的對象userDao調(diào)用addUser方法的時(shí)候會打印“添加用戶”,“記錄日志”很神奇吧,究竟發(fā)生了什么?
明明addUser方法里面只有打印”添加用戶”啊
這就是Spring AOP的強(qiáng)大之處,在運(yùn)行時(shí)通過動態(tài)代理技術(shù)對UserDao的addUser方法進(jìn)行了增強(qiáng),添加了記錄日志的功能。
動態(tài)代理其實(shí)就是在運(yùn)行時(shí)動態(tài)的生成目標(biāo)對象的代理對象,在代理對象中對目標(biāo)對象的方法進(jìn)行增強(qiáng),關(guān)于動態(tài)代理技術(shù)我會在另一篇文章中詳細(xì)介紹,現(xiàn)在先來看一下AOP中幾個(gè)重要的概念:
一:通知:就是會在目標(biāo)方法執(zhí)行前后執(zhí)行的方法
上面這個(gè)例子中:
@After(value="execution(* cn.xh.dao.UserDao.addUser(..))")
public voidlog(){
System.out.println("記錄日志");
}
這個(gè)方法就是通知,目標(biāo)方法是UserDao類的addUser(),在addUser執(zhí)行之后執(zhí)行了log方法,所以log方法是后置通知,通過在方法上加上@After注解來表示。
通過通知和目標(biāo)方法的執(zhí)行順序我們可以把通知分為五種:
前置通知(before):在目標(biāo)方法執(zhí)行之前執(zhí)行。
后置通知(after):在目標(biāo)方法執(zhí)行之后執(zhí)行
后置返回通知(after returning):在目標(biāo)方法返回之后執(zhí)行,先執(zhí)行后置通知再執(zhí)行后置返回通知。
這三種通知的執(zhí)行順序如下:
try{
try{
//@Before
method.invoke(..);
}finally{
//@After
}
//@AfterReturning
}catch(){
//@AfterThrowing
}
異常通知(after throwing):在目標(biāo)方法拋出異常時(shí)執(zhí)行
環(huán)繞通知(around):在目標(biāo)函數(shù)執(zhí)行中執(zhí)行
二:切入點(diǎn):應(yīng)用通知進(jìn)行增強(qiáng)的目標(biāo)方法
現(xiàn)在面臨的問題是如何去描述這個(gè)需要被增強(qiáng)的目標(biāo)方法,如果只是一個(gè)具體的方法需要增強(qiáng)那簡單,通過類名和方法名找到它就可以了,但是往往真實(shí)的需求中很多方法需要同樣的通知進(jìn)行增強(qiáng),Spring AOP為我們提供了一個(gè)描述方法的語法比如上例中的:
@After(value="execution(* cn.xh.dao.UserDao.addUser(..))")
execution(* cn.xh.dao.UserDao.addUser(..)就是用來描述需要應(yīng)用通知的方法的。這里的含義是cn.xh.dao包UserDao類中的參數(shù)任意,返回值任意的addUser方法。
關(guān)于這種描述更多具體的寫法我會在另一篇文章中詳述。
三:連接點(diǎn):連接點(diǎn)就是可以應(yīng)用通知進(jìn)行增強(qiáng)的方法
因?yàn)镾pring Aop只能針對方法進(jìn)行增強(qiáng),所以這里的連接點(diǎn)指的就是方法,一旦連接點(diǎn)被增強(qiáng),它就成為了切入點(diǎn)。
如上例中的:
public voidaddUser(){
System.out.println("添加用戶");
}
public voidupdateUser(){
System.out.println("修改用戶");
}
public voiddeleteUser(){
System.out.println("刪除用戶");
}
三個(gè)方法都是連接點(diǎn)。
四:切面:是切入點(diǎn)和通知的結(jié)合
可以用切面類來表示:
@Aspect
public classMyAspectLog {
/**
*方法執(zhí)行完后執(zhí)行的方法
*/
@After(value="execution(* cn.xh.dao.UserDao.addUser(..))")
public voidlog(){
System.out.println("記錄日志");
}
}
在這個(gè)類中既包含了切入點(diǎn)addUser又包含了通知:log().
看完上述內(nèi)容,你們掌握Spring AOP的使用方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝各位的閱讀!