AOP這個名詞相信大家都不陌生,尤其是在面試的過程中,面試官多多少少都會問到一些關於他的問題,這玩意兒有用嗎。答案是必然的,只是在日常商務邏輯中用的不多,一般像想在某個寫好的代碼之前插入一些內容,這種情況下用的比較多,那麼接下來我們就一起來看看他在spring boot中的使用。
項目結構如下:
1.建立項目,pom如下:
引入如下jar包即可
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency>
2.建立WebLogAspect類
在完成了引入AOP依賴包後,一般來說並不需要去做其他配置。也許在Spring中使用過註解配置方式的人會問是否需要在程式主類中增加@EnableAspectJAutoProxy來啟用,實際並不需要
package com.gwd.aop;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.After;import org.aspectj.lang.annotation.AfterReturning;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;import org.aspectj.lang.annotation.Pointcut;import org.springframework.stereotype.Component;/** * @FileName WebLogAspect.java* @Description:TODO* @author JackHisen(gu.weidong)* @version V1.0* @createtime 2018年2月27日 上午9:32:17 * 修改曆史:* 時間 作者 版本 描述*==================================================== **/@Component@Aspectpublic class WebLogAspect {@Pointcut("execution(public * com.gwd.web..*.*(..))")public void weblog() {}@Before("weblog()")public void webBefore() {System.out.println("在更新之前");System.out.println("stop");return;}@After("weblog()")public void webAfter() {System.out.println("在更新之後");}@Around("weblog()")public void webAround(ProceedingJoinPoint pjp) throws Throwable {System.out.println("環繞通知前……");pjp.proceed();System.out.println("環繞通知後……");}@AfterReturning("weblog()")public void webAfterReturn() {System.out.println("afterReturning ……");}}
實現AOP的切面主要有以下幾個要素:使用@Aspect註解將一個java類定義為切面類使用@Pointcut定義一個切入點,可以是一個規則運算式,比如下例中某個package下的所有函數,也可以是一個註解等。根據需要在切入點不同位置的切入內容使用@Before在切入點開始處切入內容使用@After在切入點結尾處切入內容使用@AfterReturning在切入點return內容之後切入內容(可以用來對處理傳回值做一些加工處理)使用@Around在切入點前後切入內容,並自己控制何時執行切入點自身的內容使用@AfterThrowing用來處理當切入內容部分拋出異常之後的處理邏輯
3.controller
package com.gwd.web;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;/** * @FileName TestController.java* @Description:TODO* @author JackHisen(gu.weidong)* @version V1.0* @createtime 2018年2月27日 上午10:03:26 * 修改曆史:* 時間 作者 版本 描述*==================================================== **/@RestControllerpublic class TestController {@RequestMapping("/testAop")public void testAop() {System.out.println("test進行中");}}
4.測試結果如下
環繞通知前……在更新之前stoptest進行中環繞通知後……在更新之後afterReturning ……
在一個方法只被一個aspect類攔截時,aspect類內部的 advice 將按照以下的順序進行執行:
正常情況:
異常情況:
最佳化:AOP切面的優先順序
由於通過AOP實現,程式得到了很好的解耦,但是也會帶來一些問題,比如:我們可能會對Web層做多個切面,校正使用者,校正頭資訊等等,這個時候經常會碰到切面的處理順序問題。
所以,我們需要定義每個切面的優先順序,我們需要@Order(i)註解來標識切面的優先順序。i的值越小,優先順序越高。假設我們還有一個切面是CheckNameAspect用來校正name必須為didi,我們為其設定@Order(10),而上文中WebLogAspect設定為@Order(5),所以WebLogAspect有更高的優先順序,這個時候執行順序是這樣的: 在@Before中優先執行@Order(5)的內容,再執行@Order(10)的內容 在@After和@AfterReturning中優先執行@Order(10)的內容,再執行@Order(5)的內容
所以我們可以這樣子總結: 在切入點前的操作,按order的值由小到大執行 在切入點後的操作,按order的值由大到小執行 部分內容來源於:http://blog.didispace.com/springbootaoplog/