【Spring 】了解Spring AOP

目錄

一、什么是Spring AOP

二、AOP的使用場景

三、AOP組成

四、Spring AOP的實現

1、添加Spring AOP依賴

2、定義切面和切點

3、定義相關通知

五、 AOP的實現原理

1、什么是動態代理?

2、 JDK代理和CGLIB代理的區別


一、什么是Spring AOP

AOP(Aspect Oriented Programming),直譯過來就是面向切面編程,AOP是一種編程思想,是面向對象編程(OOP)的一種補充。Spring AOP是AOP思想的一種實現,就像DI一樣是IoC的一種實現。

AOP的主要作用就是分離功能性需求和非功能性需求,使開發人員可以集中處理某一個關注點,減少對業務代碼的侵入。增強代碼的可讀性和可維護性簡單來所,AOP的作用就是保證開發者在不修改業務代碼的前提下,位系統中的業務組件添加某種通用功能。

就比如實現一個用戶登錄權限的校驗功能,就比如我們使用的博客,在要進入博客編輯的頁面時,需要對你是否登錄進行校驗,如果已經登錄,那么就可以進入編輯頁,如果沒有那么就需要在登錄頁面登錄之后在進入。像這樣需要登錄校驗的頁面,我們使用AOP思想,只需要在某一處配置以下,所有的需要判斷用戶登錄的頁面就可以實現用戶登錄驗證了。這樣每個頁面就只關注具體的業務邏輯了。

二、AOP的使用場景

就像上面舉的例子,當你的程序中實現的頁面越來越多,那么你要 寫的登錄驗證也越來越多,?這些?法?是相同的,這么多的?法就會代碼修改和維護的成本我們對這種功能統一,并且使用地方較多的功能,就可以考慮使用AOP來統一處理。當然AOP可以使用的場景還有很多。

  • 統一日志記錄
  • 統一方法執行時間統計
  • 統一的返回格式設置
  • 統一的異常處理
  • 事務的開啟和提交等

如果沒有使用AOP思想來寫代碼,用戶發送的請求直接被業務代碼控制層接收到,請求訪問的頁面來校驗用戶是否登錄。使用了AOP思想的代碼,用戶發送方的請求被AOP這里的代碼先進行登錄校驗,如果登錄,將請求傳給控制層,如果沒有登錄就會被攔截。

三、AOP組成

1??切面(Aspect):表示當前AOP是針對那些事件做處理的,用來登錄的還是記錄日志的。切面就是通知和切點的結合,通知和切點共同定義了切面的全部內容,他是干什么的,什么時候在哪里執行。通常以類的形式表示。

2??切點(Pointcut):表示定義具體規則。切點其實就是篩選出的連接點,一個類中的所有方法都是連接點,但又不全需要,會篩選出某些作為連接點作為切點,如果說通知定義了切面的動作后者執行時機的話,切點則定義了執行的地點。

3??通知(Advice):AOP執行的具體方法。有的地方叫增強。

4??連接點(Join point):就是有可能觸發切點的所有點。應用執行過程中能夠插入切面的一個點,這個點可以是方法調用時,異常拋出時,甚至修改字段時。切面代碼可以利用這些點插入到應用的正常流程之中,并添加新的行為。

四、Spring AOP的實現

1、添加Spring AOP依賴

在創建好的Spring Boot項目的pom.xml中添加Spring AOP的依賴,我們可以從中央倉庫中下載

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId>
</dependency>

然后點擊刷新,觸發下載。

2、定義切面和切點

這里使用注解@Aspect表示定義切面,即UserAserAspect類為切面,使用@Component注解表示讓切面隨著框架的啟動而啟動,這樣切面中的切點定義的攔截規則才能生效。

package com.example.demo.common;import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;@Aspect//定義切面
@Component//讓切面隨著框架的啟動而啟動
public class UserAspect {//定義切點,@Pointcut注解的參數中定義了具體的攔截規則。參數中使用AspectJ表達式語法@Pointcut("execution(* com.example.demo.controller.UserController.*(..))")public void pointcut(){}
}

上述代碼中,pointcut方法為空方法,它不需要又方法體,此方法名就是起到一個"標識"的作用,標識下面的通知方法具體指的是那個切點。因為一個切面中有很多切點。

上述pointcut方法上添加的@Pointcut注解的參數中使用切點表達式定義了具體的攔截規則

execution(* com.example.demo.controller.UserController.*(..))

切點表達的意思是攔截UserContrller類中的所有方法其參數為任意參數并且返回值為任意類型的返回值。

  • execution表示的意思為執行,執行的是后面跟的()中的規則。
  • *表示的多個部分組成的,有修飾符和返回值類型。
  • com.example.demo.controller.UserController表示要攔截com.example.demo.controller包中的UserController類
  • 類后面跟的*表示UserController類中的所有方法。
  • ..表示的不定式傳參

切點表達式由切點函數組成,其中execution()最常見的切點函數用來匹配方法,語法為:

execution(<修飾符><返回值類型><包.類.方法(參數)><異常>)

常見表達式示例

  • execution(* com.example.demo.User.*(..)):匹配User類中的所有方法。
  • execution(* com.example.demo.User+.*(..)):匹配該類的子類包括該類的所有方法
  • execution(* com.example.*.*(..)):匹配com.example包下的所有類的所有方法
  • execution(* com.example..*.*(..)):匹配com.example包下,子孫包下所有類的所有方法
  • execution(* addUser(String,int)):匹配addUser方法,其第一個參數類型是String,第二個參數類型是int。

創建UserController類,這個類中的方法哪一個要被執行(目標方法)哪一個就是連接點

package com.example.demo.controller;import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/user")
public class UserController {@RequestMapping("/getuser")public String getUser(){System.out.println("do getUser");return "get user";}@RequestMapping("/deluser")public String delUser(){System.out.println("do delUser");return "del user";}
}

3、定義相關通知

通知定義的是被攔截的方法具體要執行的業務。比如用戶登錄權限驗證方法就是具體要執行的業務。

Spring AOP中,可以在方法上使用以下注解,會設置方法為通知方法,在滿足條件后會通知本方法進行調用:

  • 前置通知使用@Before:通知方法會在目標方法(連接點)調用之前執行
  • 后置通知使用@After:通知方法會在目標方法(連接點)返回或者拋出異常后調用
  • 返回之后通知使用@AfterReturning:通知方法會在目標方法(連接點)返回后調用
  • 拋異常后通知使用@AfterThrowing:通知方法會在目標方法(連接點)拋出異常后調用
  • 環繞通知使用@Around:通知包裹了被通知的方法,在被通知的方法之前和調用之后執行自定義的行為。

1??前置通知和后置通知的實現

package com.example.demo.common;import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;@Aspect//定義切面
@Component//讓切面隨著框架的啟動而啟動
public class UserAspect {//定義切點,@Pointcut注解的參數中定義了具體的攔截規則@Pointcut("execution(* com.example.demo.controller.UserController.*(..))")public void pointcut(){}//定義前置通知@Before("pointcut()")//表示這個通知是針對pointcut方法的public void doBefore(){System.out.println("執行了前置通知");}//定義后置通知@After("pointcut()")public void doAfter(){System.out.println("執行了后置通知");}
}

當我們在前端頁面中訪問UserController類的方法時,后端程序的控制臺上每次出現的結果是先執行前置通知,在執行目標方法(連接點),然后執行后置通知。

?

2??環繞通知的具體實現?

環繞通知方法是具有Object類型的返回值,需要把方法執行結果返回給框架,框架拿到對象繼續執行。

package com.example.demo.common;import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;@Aspect//定義切面
@Component//讓切面隨著框架的啟動而啟動
public class UserAspect {//定義切點,@Pointcut注解的參數中定義了具體的攔截規則@Pointcut("execution(* com.example.demo.controller.UserController.*(..))")public void pointcut(){}//定義前置通知@Before("pointcut()")//表示這個通知是針對pointcut方法的public void doBefore(){System.out.println("執行了前置通知");}//定義后置通知@After("pointcut()")public void doAfter(){System.out.println("執行了后置通知");}//定義環繞通知@Around("pointcut()")//環繞通知方法的參數為要執行的連接點,也就是我們在前端訪問的目標方法public Object doAround(ProceedingJoinPoint joinPoint){System.out.println("環繞通知之前");Object result = null;try {//執行目標方法,它的目標方法就是我們在前端訪問的方法result = joinPoint.proceed();} catch (Throwable e) {e.printStackTrace();}System.out.println("環繞通知之后");return result;}
}

從執行結果中可以看到環繞通知的執行范圍,可以環繞執行通知是最先執行的,然后是執行前置通知,然后再執行目標方法,然后執行后置通知,最后所有的方法執行完成了,環繞通知方法才會執行完成。

?

五、 AOP的實現原理

Spring AOP是建立再動態代理的基礎上的,Spring對AOP的支持局限于方法級別的攔截。

Spring AOP使用兩種混合的實現方式:JDK動態代理和CGLib動態代理。

  • JDK動態代理:如果目標對象實現了InvocationHandler接口,Spring將使用JDK動態代理來創建代理對象。
  • CGLib動態代理:如果目標對象沒有實現InvocationHandler接口,Spring將使用CGLib代理,通過繼承目標對象來創建代理對象。

1、什么是動態代理?

代理可以看作是對調用目標的一個包裝,這樣我們對目標代理的調用不是直接發生的,而是通過代理完成。

當想要給實現了某個接口的類中的方法,加一些額外的處理,比如加日志,加事務等。可以給這個類創建一個代理,也就是創建一個新的類,這個類不僅包含原來類方法的功能,而且還在原來的基礎上添加了額外處理的新方法,這個代理類并不是定義好的,而是動態生成的,具有解耦意義,靈活、擴展性強。

在Java中,動態代理通常使用Java.lang.reflect.Proxy類和Java.lang.reflect.InvocationHandler接口來實現。

2、 JDK代理和CGLIB代理的區別

  • 接口要求:JDK動態代理只能對實現了接口的類生成代理;而CGLIB代理可以沒有實現接口的類,是通過繼承被代理類,在運行時動態的生成代理對象。
  • 生成方式:JDK代理使用Java的反射機制來完成代理對象,而CGLIB代理使用CGLIB庫生成代理對象,通過修改目標類的字節碼來實現。所以該類不能被final修飾

如果代理類沒有實現 InvocationHandler 接口,那么Spring AOP會選擇使用CGLIB來動態代理目標類。CGLIB(Code Generation Library),是一個代碼生成的類庫,可以在運行時動態的生成指定類的一個子類對象,并覆蓋其中特定方法并添加增強代碼,從而實現AOP。CGLIB是通過繼承的方式做的動態代理,因此如果某個類被標記為final,那么它是無法使用CGLIB做動態代理的。
?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/39639.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/39639.shtml
英文地址,請注明出處:http://en.pswp.cn/news/39639.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

PLY模型格式詳解【3D】

本文介紹PLY 多邊形文件格式&#xff0c;這是一種用于存儲被描述為多邊形集合的圖形對象。 PLY文件格式的目標是提供一種簡單且易于實現但通用的格式足以適用于各種模型。 PLY有兩種子格式&#xff1a;易于入門的 ASCII 表示形式和用于緊湊存儲和快速保存和加載的二進制格式。 …

【FastColoredTextBox】C# 開源文本編輯控件

主界面截圖 使用Demos演示 FastColoredTextBox 是一個用于在 C# 程序中實現高亮語法著色、代碼編輯和文本顯示的自定義控件。它提供了許多功能&#xff0c;包括&#xff1a; 語法高亮&#xff1a;FastColoredTextBox 支持多種語言的語法高亮&#xff0c;可以根據語法規則將不同…

write javaBean error, fastjson version 1.2.76

fastjson JSON.toJSONString 報錯&#xff1a; > [0] JavaBeanSerializer.java->541: com.alibaba.fastjson.serializer.JavaBeanSerializer->write()> [1] JavaBeanSerializer.java->154: com.alibaba.fastjson.serializer.JavaBeanSerializer->write()>…

vite4+vue3+electron23.3+ts桌面應用bs端開發 打包windows、linux、max三個系統的安裝包

vite4vue3electron23.3ts桌面應用bs端開發 打包windows、linux、max三個系統的安裝包 主要包依賴 "electron-store": "^8.1.0", //全局數據狀態管理&#xff0c;可選擇性安裝"electron": "23.3.8","electron-builder": &q…

Android 使用SQLite的案例詳解

1、說明 sqlite是個輕量級的數據庫,可用于嵌入式。有時候做本地的web開發的時候,我會把sqlite作為內置數據庫,這樣便于部署,直接啟動應用即可。 這里主要是將android中的使用過程記錄一下。主要包含,數據如何初始化,在不同的activity中如何使用,以及增刪改查的實現。 …

網頁顯示攝像頭數據的方法---基于web video server

1. 背景&#xff1a; 在ros系統中有發布攝像頭的相關驅動rgb數據&#xff0c;需求端需要將rgb數據可以直接在網頁上去顯示。 問題解決&#xff1a; web_video_server功能包&#xff0c;相關鏈接&#xff1a; web_video_server - ROS Wiki 2. 下載&#xff0c;安裝和編譯&a…

Ubuntu20 ctrl+alt+T無法打開終端

事情是這樣的&#xff0c;某天改了下python版本&#xff0c;發現linux默認打開終端的快捷鍵ctrlaltT寄了&#xff0c;網上給出的都是修改快捷鍵不出意外肯定沒用 但是幸好我們是會分析的&#xff0c;我看到&#xff0c;很多回答說新增一個快捷鍵運行的命令是gnome-terminal&…

21、stm32使用LTDC驅動LCD

注&#xff1a;本文基于stm32使用FMC驅動SDRAM(IS42S32800G-6BLI)工程繼續開發 本例使用安富萊的H743XIH板子驅動LTDC點亮7寸LCD 硬件接線&#xff1a;RGB888 一、cubemx配置 1、LTDC配置 注意此引腳應于上面的硬件接線圖一致 2、配置DMA2D 3、背光引腳和觸摸引腳 4、時鐘…

在 IntelliJ IDEA 中使用 Docker 開發指南

目錄 一、IDEA安裝Docker插件 二、IDEA連接Docker 1、Docker for Windows 連接 2、SSH 連接 3、Connection successful 連接成功 三、查看Docker面板 四、使用插件生成鏡像 一、IDEA安裝Docker插件 打開 IntelliJ IDEA&#xff0c;點擊菜單欄中的 "File" -&g…

LeetCode 778. Swim in Rising Water【最小瓶頸路;二分+BFS或DFS;計數排序+并查集;最小生成樹】2096

本文屬于「征服LeetCode」系列文章之一&#xff0c;這一系列正式開始于2021/08/12。由于LeetCode上部分題目有鎖&#xff0c;本系列將至少持續到刷完所有無鎖題之日為止&#xff1b;由于LeetCode還在不斷地創建新題&#xff0c;本系列的終止日期可能是永遠。在這一系列刷題文章…

cs231n assignment 3 Q2 Image Captioning with Vanilla RNNs

文章目錄 嫌啰嗦直接看代碼Q2 Image Captioning with Vanilla RNNs一個給的工具代碼里的bug問題展示問題解決思路解決辦法 rnn_step_forward題面解析代碼輸出 rnn_step_backward題面解析代碼輸出 rnn_forward題面解析代碼輸出 rnn_backward題面解析代碼輸出 word_embedding_for…

使用 BERT 進行文本分類 (02/3)

? 一、說明 在使用BERT&#xff08;1&#xff09;進行文本分類中&#xff0c;我向您展示了一個BERT如何標記文本的示例。在下面的文章中&#xff0c;讓我們更深入地研究是否可以使用 BERT 來預測文本是使用 PyTorch 傳達積極還是消極的情緒。首先&#xff0c;我們需要準備數據…

3.1 Qt樣式選擇器

本期內容 3.1 樣式選擇器 3.1.1 Universal Selector (通用選擇器) 3.1.2 Type Selector (類型選擇器) 3.1.3 Property Selector (屬性選擇器) 3.1.4 Class Selector (類選擇器) 3.1.5 ID Selector (ID選擇器) 3.1.6 Descendant Selector (后裔選擇器) 3.1.7 Chil…

前端跨域的原因以及解決方案(vue),一文讓你真正理解跨域

跨域這個問題,可以說是前端的必需了解的,但是多少人是知其然不知所以然呢&#xff1f; 下面我們來梳理一下vue解決跨域的思路。 什么情況會跨域&#xff1f; ? 跨域的本質就是瀏覽器基于同源策略的一種安全手段。所謂同源就是必須有以下三個相同點&#xff1a;協議相同、域名…

WinCC V7.5 中的C腳本對話框不可見,將編輯窗口移動到可見區域的具體方法

WinCC V7.5 中的C腳本對話框不可見&#xff0c;將編輯窗口移動到可見區域的具體方法 由于 Windows 系統更新或使用不同的顯示器&#xff0c;在配置C動作時&#xff0c;有可能會出現C腳本編輯窗口被移動到不可見區域的現象。 由于該窗口無法被關閉&#xff0c;故無法進行進一步…

KafkaStream:Springboot中集成

1、在kafka-demo中創建配置類 配置kafka參數 package com.heima.kafkademo.config;import lombok.Data; import org.apache.kafka.common.serialization.Serdes; import org.apache.kafka.streams.StreamsConfig; import org.springframework.boot.context.properties.Configu…

8月11日上課內容 nginx的多實例和動靜分離

多實例部署 在一臺服務器上有多個tomcat的服務。 配置多實例之前&#xff0c;看單個實例是否訪問正常。 1.安裝好 jdk 2.安裝 tomcat cd /opt tar zxvf apache-tomcat-9.0.16.tar.gz mkdir /usr/local/tomcat mv apache-tomcat-9.0.16 /usr/local/tomcat/tomcat1 cp -a /u…

Linux系統管理:虛擬機ESXi安裝

目錄 一、理論 1.VMware Workstation 2.VMware vSphere Client 3.ESXi 二、實驗 1.ESXi 7安裝 一、理論 1.VMware Workstation 它是一款專業的虛擬機軟件&#xff0c;可以在一臺物理機上運行多個操作系統&#xff0c;支持Windows、Linux等操作系統&#xff0c;可以模擬…

使用selenium如何實現自動登錄

回顧使用requests如何實現自動登錄一文中&#xff0c;提到好多網站在我們登錄過后&#xff0c;在之后的某段時間內訪問該網頁時&#xff0c;不會給出請登錄的提示&#xff0c;時間到期后就會提示請登錄&#xff01;這樣在使用爬蟲訪問網頁時還要登錄&#xff0c;打亂我們的節奏…

item_get_sales-獲取商品銷量詳情

一、接口參數說明&#xff1a; item_get_sales-獲取商品銷量詳情&#xff0c;點擊更多API調試&#xff0c;請移步注冊API賬號點擊獲取測試key和secret 公共參數 請求地址: https://api-gw.onebound.cn/taobao/item_get_sales 名稱類型必須描述keyString是調用key&#xff08…