SpringBoot整合Web之AOP配置詳解
配置AOP
AOP簡(jiǎn)介
要介紹面向切面變成(Aspect-Oriented Programming,AOP),需要先考慮一個(gè)這樣的場(chǎng)景:公司有一個(gè)人力資源管理系統(tǒng)目前已經(jīng)上線,但是系統(tǒng)運(yùn)行不穩(wěn)定,有時(shí)運(yùn)行的很慢,為了檢測(cè)到底是哪個(gè)環(huán)節(jié)出現(xiàn)問題了,開發(fā)人員想要監(jiān)控每一個(gè)方法執(zhí)行的時(shí)間,再根據(jù)這些執(zhí)行時(shí)間判斷出問題所在。當(dāng)問題解決后,再把這些監(jiān)控移除掉。系統(tǒng)目前已經(jīng)運(yùn)行,如果手動(dòng)修改系統(tǒng)成千上萬個(gè)方法,工作量太大,而且這些監(jiān)控方法以后還要移除掉;如果能夠在系統(tǒng)運(yùn)行過程中動(dòng)態(tài)添加代碼,就能很好的解決問題。這種在系統(tǒng)運(yùn)行時(shí)動(dòng)態(tài)添加代碼的方式成為面向切面編程(AOP)。Spring Boot 對(duì) AOP 提供了很好的支持。在 AOP 中,有一些常見的概念需要了解:
- Joinpoint(連接點(diǎn)):類里面可以被增強(qiáng)的方法即為連接點(diǎn)。例如,想修改那個(gè)方法的功能,那么該方法就是一個(gè)連接點(diǎn)
- Pointcut(切入點(diǎn)):對(duì) Joinpoint 進(jìn)行攔截的定義即為切入點(diǎn)。例如,攔截所有以 insert 開始的方法,這個(gè)定義即為切入點(diǎn)
- Advice(通知):攔截到 Joinpoint 之后所要做的事情就是通知。例如,之前說到的打印日志監(jiān)控。通知分為前置通知、后置通知、異常通知、最終通知、環(huán)繞通知
- Aspect(切面):Pointcut 和 Advice 的結(jié)合
- Target(目標(biāo)對(duì)象):要增強(qiáng)的類成為 Target
Spring Boot 支持
Spring Boot 在 Spring 的基礎(chǔ)上對(duì) AOP 的配置提供了自動(dòng)化配置解決方案 spring-boot-starter-aop ,首先引入依賴,如下:
<!-- AOP 依賴 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
然后在com.sang.aop.service 包下創(chuàng)建 UserService 類,如下:
@Service public class UserService { public String getUserById(Integer id){ System.out.println("get..."); return "user"; } public void deleteUserById(Integer id){ System.out.println("delete..."); } }
然后創(chuàng)建切面,如下:
@Component @Aspect public class LogAspect { @Pointcut("execution(* com.sang.aop.service.*.*(..))") public void pc1() { } @Before(value = "pc1()") public void before(JoinPoint jp) { String name = jp.getSignature().getName(); System.out.println(name + "方法開始執(zhí)行..."); } @After(value = "pc1()") public void after(JoinPoint jp) { String name = jp.getSignature().getName(); System.out.println(name + "方法執(zhí)行結(jié)束..."); } @AfterReturning(value = "pc1()", returning = "result") public void afterReturning(JoinPoint jp, Object result) { String name = jp.getSignature().getName(); System.out.println(name + "方法返回值為:" + result); } @AfterThrowing(value = "pc1()",throwing = "e") public void afterThrowing(JoinPoint jp, Exception e) { String name = jp.getSignature().getName(); System.out.println(name+"方法拋異常了,異常是:"+e.getMessage()); } @Around("pc1()") public Object around(ProceedingJoinPoint pjp) throws Throwable { return pjp.proceed(); } }
代碼解釋:
- @Aspect 注解表明這是一個(gè)切面類
- pc1() 方法使用了 @Pointcut() 注解 ,這是一個(gè)切入點(diǎn)定義。execution 中的第一個(gè) * 表示方法返回任意值,第二個(gè) * 表示 service 包下的任意類,第三個(gè) * 表示類中的任意方法,括號(hào)中的兩個(gè)點(diǎn)表示方法參數(shù)任意,即這里描述的切入點(diǎn)為 service 包下所有類中的所有方法
- before() 方法使用了 @Before注解 ,表示這是一個(gè)前置通知,該方法在目標(biāo)方法執(zhí)行之前執(zhí)行。通過 JoinPoint 參數(shù)可以獲取目標(biāo)方法的方法名、修飾符等信息
- after() 方法使用了 @After注解,表示這是一個(gè)后置通知,該方法在目標(biāo)方法執(zhí)行之后執(zhí)行
- afterReturning() 方法使用了 @AfterReturning 注解,表示這是一個(gè)返回通知,在該方法中可以獲取目標(biāo)方法的返回值。@AfterReturning 注解的 returning 參數(shù)是指返回值的變量名,對(duì)應(yīng)方法的參數(shù)。注意,在方法參數(shù)中定義了 result 的類型為 Object ,表示目標(biāo)方法的返回值可以使任意類型,若 result 參數(shù)的類型為 Long ,則該方法只能處理目標(biāo)方法返回值為 Long 的情況
- afterThrowing() 方法使用了 @AfterThrowing 注解,表示這是一個(gè)異常通知,即當(dāng)目標(biāo)方法發(fā)生異常時(shí),該方法會(huì)被調(diào)用,異常類型為 Exception 表示所有的異常都會(huì)進(jìn)入該方法中執(zhí)行,若異常類型為 ArithmeticException ,則表示只有目標(biāo)方法拋出 ArithmeticException 異常時(shí)才會(huì)進(jìn)入該方法處理
- around() 方法使用了 @Around 注解,表示這是一個(gè)環(huán)繞通知。環(huán)繞通知是所有通知里功能最為強(qiáng)大的通知,可以實(shí)現(xiàn)前置通知、后置通知、異常通知以及返回通知的功能。目標(biāo)方法進(jìn)入環(huán)繞通知后,通過調(diào)用 ProceedingJoinPoint 對(duì)象的 proceed 方法使目標(biāo)方法繼續(xù)執(zhí)行,開發(fā)者可以在此修改目標(biāo)方法的執(zhí)行參數(shù)、返回值等,并且可以在此處理目標(biāo)方法的異常
配置完成后,接下來在Controller 中創(chuàng)建接口,分別調(diào)用 Userservice 中的兩個(gè)方法,即可看到 LogAspect 中的代碼動(dòng)態(tài)的嵌入目標(biāo)方法中執(zhí)行了,如下:
getUserById方法開始執(zhí)行...
get...
getUserById方法返回值為:user
getUserById方法執(zhí)行結(jié)束...
deleteUserById方法開始執(zhí)行...
delete...
deleteUserById方法返回值為:null
deleteUserById方法執(zhí)行結(jié)束...
其它
自定義歡迎頁
Spring Boot 項(xiàng)目在啟動(dòng)后,首先會(huì)去靜態(tài)資源路徑下查找 index.html 作為首頁文件,若查找不到,則會(huì)去查找動(dòng)態(tài)的 index.html 作為首頁文件。
例如,如果想使用靜態(tài)的 index.html 頁面作為項(xiàng)目的首頁,只需在 resources/static 目錄下創(chuàng)建 index.html 文件疾苦。若想使用動(dòng)態(tài)頁面作為項(xiàng)目首頁,則需在 resources/templages 目錄下創(chuàng)建 index.html (使用Thymeleaf 模板) 或者 index.ftl(使用 FreeMarker 模板),然后在 Controller 中返回邏輯視圖名,如下:
@Controller public class IndexController { @RequestMapping("/index") public String index(){ return "index"; } }
運(yùn)行項(xiàng)目,輸入"http://localhost:8081",查看結(jié)果
自定義 favicon
favicon.ico 是瀏覽器選項(xiàng)卡左上角的圖標(biāo),可以放在靜態(tài)資源路徑下或者類路徑下,靜態(tài)資源路徑下的 favicon.ico 優(yōu)先級(jí)高于類路徑下的 favicon.ico
可以使用在線轉(zhuǎn)換網(wǎng)站:https://www.bitbug.net/ 將一張普通圖片轉(zhuǎn)為 .ico 圖片,轉(zhuǎn)換成功后,將文件重命名為 favicon.ico ,然后復(fù)制到 resources/static 目錄下,如圖
啟動(dòng)項(xiàng)目,查看效果
注意:清緩存,然后 Ctrl+F5 強(qiáng)制刷新
除去某個(gè)自動(dòng)配置
Spring Boot 中提供了大量的自動(dòng)化配置類,在 Spring Boot 的入口類上有一個(gè) @SpringBootApplication 注解。該注解是一個(gè)組合注解,由 @SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan 組成,其中 @EnableAutoConfiguration 注解開啟自動(dòng)化配置,相關(guān)的自動(dòng)化配置就會(huì)被使用。如果開發(fā)者不想使用某個(gè)自動(dòng)化配置,按如下方式除去相關(guān)配置即可:
@SpringBootApplication @EnableAutoConfiguration(exclude = {ErrorMvcAutoConfiguration.class}) public class Chapter04Application { public static void main(String[] args) { SpringApplication.run(Chapter04Application.class, args); } }
在 @EnableAutoConfiguration 注解中使用 exclude 屬性去除 Error 的自動(dòng)化配置類,這時(shí)如果在 resources/static/error 目錄下創(chuàng)建 4xx.htnl、5xx.html ,訪問出錯(cuò)時(shí)就不會(huì)自動(dòng)跳轉(zhuǎn)了。由于 @EnableAutoConfiguration 注解的 exclude 屬性值是一個(gè)數(shù)組,因此有多個(gè)要排除的自動(dòng)化配置文件只需要繼續(xù)添加即可。除了這種配置方式外,也可在 application.properties 中配置,如下:
spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration
添加前
添加后
到此這篇關(guān)于SpringBoot整合Web之AOP配置詳解的文章就介紹到這了,更多相關(guān)SpringBoot AOP配置內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring Boot 通過 Mvc 擴(kuò)展方便進(jìn)行貨幣單位轉(zhuǎn)換的代碼詳解
這篇文章主要介紹了Spring Boot 通過 Mvc 擴(kuò)展方便進(jìn)行貨幣單位轉(zhuǎn)換,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-12-12java 線程方法join簡(jiǎn)單用法實(shí)例總結(jié)
這篇文章主要介紹了java 線程方法join簡(jiǎn)單用法,結(jié)合實(shí)例形式總結(jié)分析了Java線程join方法的功能、原理及使用技巧,需要的朋友可以參考下2019-11-11Java橋接模式實(shí)例詳解【簡(jiǎn)單版與升級(jí)版】
這篇文章主要介紹了Java橋接模式,結(jié)合實(shí)例形式分析了java橋接模式簡(jiǎn)單版與升級(jí)版兩種實(shí)現(xiàn)技巧,需要的朋友可以參考下2019-07-07Java實(shí)用工具之使用oshi獲取主機(jī)信息的方法
這篇文章主要介紹了Java實(shí)用工具之使用oshi獲取主機(jī)信息的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-02-02Object類toString()和equals()方法使用解析
這篇文章主要介紹了Object類toString()和equals()方法使用解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-02-02本地啟動(dòng)RocketMQ未映射主機(jī)名產(chǎn)生的超時(shí)問題最新解決方案
這篇文章主要介紹了本地啟動(dòng)RocketMQ未映射主機(jī)名產(chǎn)生的超時(shí)問題,本文給大家分享最新解決方案,感興趣的朋友跟隨小編一起看看吧2024-02-02java求100以內(nèi)的素?cái)?shù)示例分享
素?cái)?shù)是指因數(shù)只有1和本身的數(shù)字,這篇文章主要介紹了java求100以內(nèi)的素?cái)?shù)示例,需要的朋友可以參考下2014-03-03