日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

SpringBoot基础篇AOP之基本使用姿势小结

發布時間:2024/1/17 javascript 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 SpringBoot基础篇AOP之基本使用姿势小结 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

原文:190301-SpringBoot基礎篇AOP之基本使用姿勢小結

一般來講,談到Spring的特性,繞不過去的就是DI(依賴注入)和AOP(切面),在將bean的系列中,說了DI的多種使用姿勢;接下來看一下AOP的玩法

I. 背景知識

在實際使用之前有必要了解一下什么是AOP,以及AOP的幾個基本概念

1. advice

  • before: 在方法執行之前被調用
  • after: 在方法執行之后調用
  • after returning: 方法執行成功之后
  • after throwing: 方法拋出異常之后
  • around: 環繞,自己在內部決定方法的執行時機,因此可以在之前之后做一些業務邏輯

2. join point

連接點,比如方法調用,方法執行,字段設置/獲取、異常處理執行、類初始化、甚至是 for 循環中的某個點

但 Spring AOP 目前僅支持方法執行 (method execution)

簡單來說,Spring AOP中,PointCut就是那個被攔截的方法

3. pointcut

切點,用來描述滿足什么規則的方法會被攔截

  • 正則表達式 : @Before("execution(public * com.git.hui.demo.base.bean.*.*(..))")
  • 注解攔截方式 :@Around("@annotation(parameterCheck)")

4. aspect

切面是切點和通知的結合。通知和切點共同定義了關于切面的全部內容,它是什么時候,在何時和何處完成功能

5. introduction

引入允許我們向現有的類添加新的方法或者屬性

6. weaving

組裝方面來創建一個被通知對象。這可以在編譯時完成(例如使用AspectJ編譯器),也可以在運行時完成。Spring和其他純Java AOP框架一樣,在運行時完成織入。

簡單來講就是生成一個代理類,在調用被攔截的方法時,實際上執行的是代理類,這個代理類內部執行切面邏輯

II. 使用說明

1. 基本配置

首先是基本環境的搭建, 先貼上必要的xml配置, 使用aop需要引入包: spring-boot-starter-aop

<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.0.4.RELEASE</version><relativePath/> <!-- lookup parent from repository --> </parent><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><spring-cloud.version>Finchley.RELEASE</spring-cloud.version><java.version>1.8</java.version> </properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency> </dependencies><build><pluginManagement><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></pluginManagement> </build><repositories><repository><id>spring-milestones</id><name>Spring Milestones</name><url>https://repo.spring.io/milestone</url><snapshots><enabled>false</enabled></snapshots></repository> </repositories> 復制代碼

2. 代碼準備

首先創建一個被攔截的bean: com.git.hui.boot.aop.demo.DemoBean,如下

@Component public class DemoBean {/*** 返回隨機的字符串** @param time* @return*/public String randUUID(long time) {try {System.out.println("in randUUID before process!");return UUID.randomUUID() + "|" + time;} finally {System.out.println("in randUUID finally!");}} } 復制代碼

接著在啟動類中,執行

@SpringBootApplication public class Application {public Application(DemoBean demoBean) {String ans = demoBean.randUUID(System.currentTimeMillis());System.out.println("----- ans: " + ans + "---------");}public static void main(String[] args) {SpringApplication.run(Application.class);} } 復制代碼

3. AOP使用

在實際使用之前,需要創建一個切面,用@Aspect聲明,其次切面也需要作為bean托付給Spring容器管理

@Aspect @Component public class AnoAspcet { } 復制代碼

a. before

在方法調用之前,需要執行一些操作,這個時候可以使用 @Before 注解來聲明before advice

一種可使用姿勢如下,我們的切點直接在注解中進行定義,使用正則表達式的方式

@Before("execution(public * com.git.hui.boot.aop.demo.*.*(*))") public void doBefore(JoinPoint joinPoint) {System.out.println("do in Aspect before method called! args: " + JSON.toJSONString(joinPoint.getArgs())); } 復制代碼

b. after

在方法調用完畢之后,再執行一些操作,這個時候after就可以派上用場,為了考慮切點的通用性,我們可以考慮聲明一個切點,使用@Pointcut注解

@Pointcut("execution(public * com.git.hui.boot.aop.demo.*.*(*))") public void point() { } 復制代碼

使用pointcut的方式也比較簡單,如下

@After("point()") public void doAfter(JoinPoint joinPoint) {System.out.println("do in Aspect after method called! args: " + JSON.toJSONString(joinPoint.getArgs())); } 復制代碼

c. after returning

在正常返回結果之后,再次執行,這個也挺有意思的,通常使用這個advice時,一般希望獲取返回結果,那么應該怎么處理呢?

  • org.aspectj.lang.annotation.AfterReturning#returning 指定返回結果對應參數name
  • 返回結果作為參數傳入,要求類型一致,否則不生效
/*** 執行完畢之后,通過 args指定參數;通過 returning 指定返回的結果,要求返回值類型匹配** @param time* @param result*/ @AfterReturning(value = "point() && args(time)", returning = "result") public void doAfterReturning(long time, String result) {System.out.println("do in Aspect after method return! args: " + time + " ans: " + result); } 復制代碼

d. around

這個也比較常見,在方法執行前后干一些事情,比如常見的耗時統計,日志打印,安全控制等,很多都是基于around advice實現的

使用這個advice需要注意的是傳入參數類型為 ProceedingJoinPoint,需要在方法內部顯示執行org.aspectj.lang.ProceedingJoinPoint#proceed()來表示調用方法

@Around("point()") public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {System.out.println("do in Aspect around ------ before");Object ans = joinPoint.proceed();System.out.println("do in Aspect around ------- over! ans: " + ans);return ans; } 復制代碼

e. 輸出

執行之后輸出如下

do in Aspect around ------ before do in Aspect before method called! args: [1551433188205] in randUUID before process! in randUUID finally! do in Aspect around ------- over! ans: 6849544b-160e-464c-80bd-641f2651c6c1|1551433188205 do in Aspect after method called! args: [1551433188205] do in Aspect after method return! args: 1551433188205 ans: 6849544b-160e-464c-80bd-641f2651c6c1|1551433188205 ----- ans: 6849544b-160e-464c-80bd-641f2651c6c1|1551433188205--------- 復制代碼

從輸出結果上,可以看到每個advice的使用范圍,當然也帶來了一些疑問

  • 可以存在多個同類型的advice,攔截同一個目標嗎?(如兩個around都攔截methodA方法,那么methodA方法被調用時,兩個around advice是否都會執行)
  • 多個advice之間的優先級怎么定義?
  • aop攔截的目標方法有沒有限制(對非public的方法可以攔截么?)
  • 被攔截的方法中存在相互調用的時候,會怎樣?(如methodA,methodB都可以被攔截,且methodA中調用了methodB,那么在執行methodA時,methodB的各種advice是否會被觸發?)
  • 基于注解的aop方式可以怎樣用

以上這些問題留在下一篇進行介紹

III. 其他

0. 項目

  • 工程:github.com/liuyueyi/sp…
  • 項目: github.com/liuyueyi/sp…

1. 一灰灰Blog

  • 一灰灰Blog個人博客 blog.hhui.top
  • 一灰灰Blog-Spring專題博客 spring.hhui.top

一灰灰的個人博客,記錄所有學習和工作中的博文,歡迎大家前去逛逛

2. 聲明

盡信書則不如,以上內容,純屬一家之言,因個人能力有限,難免有疏漏和錯誤之處,如發現bug或者有更好的建議,歡迎批評指正,不吝感激

  • 微博地址: 小灰灰Blog
  • QQ: 一灰灰/3302797840

3. 掃描關注

一灰灰blog

知識星球

總結

以上是生活随笔為你收集整理的SpringBoot基础篇AOP之基本使用姿势小结的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。