Spring Boot 中的 AOP,到底是 JDK 動態代理還是 Cglib 動態代理

大家都知道,AOP 底層是動態代理,而 Java 中的動態代理有兩種實現方式:

  • 基于 JDK 的動態代理

  • 基于 Cglib 的動態代理

這兩者最大的區別在于基于 JDK 的動態代理需要被代理的對象有接口,而基于 Cglib 的動態代理并不需要被代理對象有接口。

那么,Spring 中的 AOP 是怎么實現的?是基于 JDK 的動態代理還是基于 Cglib 的動態代理?

1. Spring

先來說結論,Spring 中的動態代理,具體用哪種,分情況:

  • 如果代理對象有接口,就用 JDK 動態代理,否則就是 Cglib 動態代理。

  • 如果代理對象沒有接口,那么就直接是 Cglib 動態代理。

來看看這段來自官方文檔的說辭:

可以看到,即使在最新版的 Spring 中,依然是如上策略不變。即能用 JDK 做動態代理就用 JDK,不能用 JDK 做動態代理就用 Cglib,即首選 JDK 做動態代理。

2. Spring Boot?

Spring Boot 和 Spring 一脈相承,那么在動態代理這個問題上是否也是相同的策略呢?抱歉,這個還真不一樣。

Spring Boot 中對這個問題的處理,以 Spring Boot2.0 為節點,前后不一樣。

在 Spring Boot2.0 之前,關于 Aop 的自動化配置代碼是這樣的(Spring Boot?1.5.22.RELEASE):

@Configuration
@ConditionalOnClass({ EnableAspectJAutoProxy.class, Aspect.class, Advice.class })
@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)
public class AopAutoConfiguration {@Configuration@EnableAspectJAutoProxy(proxyTargetClass = false)@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false",matchIfMissing = true)public static class JdkDynamicAutoProxyConfiguration {}@Configuration@EnableAspectJAutoProxy(proxyTargetClass = true)@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",matchIfMissing = false)public static class CglibAutoProxyConfiguration {}}

可以看到,這個自動化配置主要是在討論 application.properties 配置文件中的?spring.aop.proxy-target-class?屬性的值。

具體起作用的是?@ConditionalOnProperty?注解,關于這個注解中的幾個屬性,也來稍微說下:

  • prefix:配置文件的前綴。

  • name:配置文件的名字,和 prefix 共同組成配置的 key。

  • having:期待配置的值,如果實際的配置和 having 的值相同,則這個配置就會生效,否則不生效。

  • matchIfMissing:如果開發者沒有在 application.properties 中進行配置,那么這個配置類是否生效。

基于如上介紹,很容易看出:

  • 如果開發者設置了?spring.aop.proxy-target-class?為 false,則使用 JDK 代理。

  • 如果開發者設置了?spring.aop.proxy-target-class?為 true,則使用 Cglib 代理。

  • 如果開發者一開始就沒配置?spring.aop.proxy-target-class?屬性,則使用 JDK 代理。

這是 Spring Boot 2.0 之前的情況。

再來看看 Spring Boot 2.0(含)之后的情況(Spring Boot?2.0.0.RELEASE):

@Configuration
@ConditionalOnClass({ EnableAspectJAutoProxy.class, Aspect.class, Advice.class,AnnotatedElement.class })
@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)
public class AopAutoConfiguration {@Configuration@EnableAspectJAutoProxy(proxyTargetClass = false)@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false", matchIfMissing = false)public static class JdkDynamicAutoProxyConfiguration {}@Configuration@EnableAspectJAutoProxy(proxyTargetClass = true)@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true", matchIfMissing = true)public static class CglibAutoProxyConfiguration {}}

可以看到,大部分配置都是一樣的,有一個地方不太相同,那就是 matchIfMissing 屬性的值。可以看到,從 Spring Boot2.0 開始,如果用戶什么都沒有配置,那么默認情況下使用的是 Cglib 代理。

3. 實踐

最后可以寫一個簡單的例子驗證一下上面的理論。

首先創建一個 Spring Boot 項目(本案例使用最新版 Spring Boot,即默認使用 Cglib 代理),加入三個依賴即可,如下:

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

接下來創建一個 IUserService 接口,如下:

public interface IUserService {void hello();}

然后再來創建一個該接口的實現類:

@Service
public class UserServiceImpl implements IUserService {@Overridepublic void hello() {}}

方法不用實現。

再來一個簡單的切面:

@Aspect
@Component
@EnableAspectJAutoProxy
public class LogAspect {@Before("execution(* org.lzx.demo.UserServiceImpl.*(..))")public void before(JoinPoint jp) {System.out.println("jp.getSignature().getName() = " + jp.getSignature().getName());}}

最后再來一個簡單的測試方法,注入 IUserService 實例:

@RestController
public class HelloController {@Autowiredprivate IUserService iUserService;@GetMapping("/hello")public void hello() {iUserService.hello();}}

DBUEG 運行一下,就可以看到 IUserService 是通過 Cglib 來代理的。

如果我們想用 JDK 來代理,那么只需要在 application.properties 中添加如下配置即可:

spring.aop.proxy-target-class=false

添加完成后,重新 DEBUG,如下圖:

可以看到,已經使用了 JDK 動態代理了。

如果用的是 Spring Boot 1.5.22.RELEASE 這個版本,那么即使不在 application.properties 中添加配置,默認也是 JDK 代理。?

4. 小結

總結一下:

  1. Spring 中的 AOP,有接口就用 JDK 動態代理,沒有接口就用 Cglib 動態代理。

  2. Spring Boot 中的 AOP,2.0 之前和 Spring 一樣;2.0 之后首選 Cglib 動態代理,如果用戶想要使用 JDK 動態代理,需要自己手動配置。

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

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

相關文章

list

目錄 迭代器 介紹 種類 本質 介紹 模擬實現 注意點 代碼 迭代器 介紹 在C中&#xff0c;迭代器&#xff08;Iterators&#xff09;是一種用于遍歷容器&#xff08;如數組、vector、list等&#xff09;中元素的工具 無論容器的具體實現細節如何,訪問容器中的元素的方…

在ubuntu中將dict.txt導入到數據庫sqlite3

將dict.txt導入到數據庫 #include <head.h> #include <sqlite3.h> int do_insert(int i,char *str,sqlite3 *db); int main(int argc, const char *argv[]) {//創建泵打開一個數據庫sqlite3 *db NULL;if(sqlite3_open("./my.db",&db) ! SQLITE_OK){…

【TI-CCS筆記】工程編譯配置 bin文件的編譯和生成 各種架構的Post-build配置匯總

【TI-CCS筆記】工程編譯配置 bin文件的編譯和生成 各種架構的Post-build配置匯總 TI編譯器分類 在CCS按照目錄下 有個名為${CG_TOOL_ROOT}的目錄 其下就是當前工程的編譯器 存放目錄為&#xff1a; C:\ti\ccs1240\ccs\tools\compiler按類型分為五種&#xff1a; ti-cgt-arm…

2023年排行前五的大規模語言模型(LLM)

2023年排行前五的大規模語言模型(LLM) 截至2023年&#xff0c;人工智能正在風靡全球。它已經成為熱門的討論話題&#xff0c;吸引了數百萬人的關注&#xff0c;不僅限于技術專家和研究人員&#xff0c;還包括來自不同背景的個人。人們對人工智能熱情高漲的原因之一是其在人類多…

CS5263替代停產IT6561連接DP轉HDMI音視頻轉換器ASL 集睿致遠CS5263設計電路原理圖

ASL集睿致遠CS5263是一款DP1.4到HDMI2.0b轉換器芯片&#xff0c;設計用于將DP1.4源連接到HDMI2.0b接收器。 CS5263功能特性&#xff1a; DP接口包括4條主通道、輔助通道和HPD信號。接收器支持每通道5.4Gbps&#xff08;HBR2&#xff09;數據速率。DP接收機結合了HDCP1.4和HDCP…

NVIDIA Omniverse與GPT-4結合生成3D內容

全球各行業對 3D 世界和虛擬環境的需求呈指數級增長。3D 工作流程是工業數字化的核心&#xff0c;開發實時模擬來測試和驗證自動駕駛車輛和機器人&#xff0c;操作數字孿生來優化工業制造&#xff0c;并為科學發現鋪平新的道路。 如今&#xff0c;3D 設計和世界構建仍然是高度…

C#的 Settings.Settings配置文件的使用方法

1、定義 在Settings.settings文件中定義配置字段。把作用范圍定義為&#xff1a;User則運行時可更改(用戶范圍的字段數據更改存儲在用戶信息中&#xff0c;不在該程序文件中)&#xff0c;Applicatiion則運行時不可更改。可以使用數據網格視圖(VS軟件的Properties 下面的Setting…

常見的Redux問題

在React中使用Redux的面試題目通常涵蓋了Redux的基本概念、工作原理、如何在React應用中集成Redux等方面。以下是一些常見的Redux問題&#xff1a; Redux的核心概念&#xff1a; 1、什么是Redux&#xff1f;它解決了什么問題&#xff1f; 它是一個狀態管理庫&#xff0c;解決…

2023國賽數學建模思路 - 復盤:校園消費行為分析

文章目錄 0 賽題思路1 賽題背景2 分析目標3 數據說明4 數據預處理5 數據分析5.1 食堂就餐行為分析5.2 學生消費行為分析 建模資料 0 賽題思路 &#xff08;賽題出來以后第一時間在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 賽題背景 校園一卡通是集…

個保新標 | 《信息安全技術 敏感個人信息處理安全要求》(征求意見稿)發布

8 月 9 日&#xff0c;全國信息安全標準化技術委員會公開發布關于國家標準《信息安全技術 敏感個人信息處理安全要求》&#xff08;征求意見稿&#xff09;&#xff08;以下簡稱《標準》&#xff09;的通知&#xff0c;面向社會廣泛征求意見。 《標準》的制定背景是為支撐《個人…

《Go 語言第一課》課程學習筆記(一)

配好環境&#xff1a;選擇一種最適合你的 Go 安裝方法 選擇 Go 版本 一般情況下&#xff0c;建議采用最新版本。因為 Go 團隊發布的 Go 語言穩定版本的平均質量一直是很高的&#xff0c;少有影響使用的重大 bug。可以根據不同實際項目需要或開源社區的情況使用不同的版本。 有…

攻擊LNMP架構Web應用

環境配置(centos7) 1.php56 php56-fpm //配置epel yum install epel-release rpm -ivh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm//安裝php56&#xff0c;php56-fpm及其依賴 yum --enablereporemi install php56-php yum --enablereporemi install php…

常見的字符編碼有哪些?有什么區別?

目錄 面試回答 知識擴展 Unicode 和 UTF-8 有啥關系&#xff1f; 有了 UTF-8&#xff0c;為什么要出現 GBK 為什么會出現亂碼 面試回答 就像電報只能發出“滴”和“答”聲一樣&#xff0c;計算機只認為 0 和1 兩種字符&#xff0c;但是&#xff0c;人類的文字是多種多樣的&…

B樹和B+樹區別

B樹和B樹的區別 B樹 B樹被稱為平衡樹&#xff0c;在B樹中&#xff0c;一個節點可以有兩個以上的子節點。B樹的高度為log M N。在B樹中&#xff0c;數據按照特定的順序排序&#xff0c;最小值在左側&#xff0c;最大值在右側。 B樹是一種平衡的多分樹&#xff0c;通常我們說m階…

什么是網絡地址轉換 (NAT)

網絡地址轉換&#xff08;NAT&#xff09;是更改源和目標 IP 地址和端口的過程&#xff0c;地址轉換減少了對 IPv4 公共地址的需求&#xff0c;并隱藏了專用網絡地址范圍&#xff0c;該過程通常由路由器或防火墻完成。 NAT是如何工作的 NAT 允許單個設備&#xff08;如路由器…

rhel 8.7 部署 keepalived+haproxy 實現 mysql 雙主高可用場景

文章目錄 [toc]部署 mysql關閉防火墻關閉 selinux創建相關目錄創建 mysql 用戶配置 PATH 變量驗證 mysql 命令切換到 mysql 用戶在 172.72.0.116 生成配置文件在 172.72.0.137 生成配置文件mysql 初始化啟動 mysql 服務修改 mysql 的 root 用戶密碼配置主從關系172.72.0.137 配…

數字化格局下的引領者:百望云通過強制性國家標準GB18030-2022最高級別認證

8月1日,強制性國家標準GB 18030-2022《信息技術 中文編碼字符集》實施。8月15日,百望云“綠頁閱讀器”正式通過中國電子技術標準化研究院強制性國家標準GB18030-2022《信息技術 中文編碼字符集》最高級(實現級別3)認證,彰顯了百望云在數字化信息處理領域對標國家標準的卓越技術…

Android CameraX適配Android13的踩坑之路

AndroidCameraX適配Android13的踩坑之路 前言&#xff1a; 最近把AGP插件升級到8.1.0&#xff0c;新建項目的時候目標版本和編譯版本都是33&#xff0c;發現之前的demo使用Camerax拍照和錄像都失敗了&#xff0c;于是查看了一下官網和各種資料&#xff0c;找到了Android13的適…

網絡編程(12): TCP重傳、滑動窗口、流量控制、擁塞控制

1、TCP重傳機制 通過序列號和確認號確保可靠傳輸&#xff0c;當發送端發送數據給接收到&#xff0c;接收端會返回一個確認號&#xff0c;表示收到消息了 超時重傳&#xff1a;沒有在指定時間內收到ACK報文 超時重傳的兩種可能&#xff1a;數據包丟失、確認包丟失超時重傳時間RT…

第十三課:QtCmd 命令行終端應用程序開發

功能描述&#xff1a;開發一個類似于 Windows 命令行提示符或 Linux 命令行終端的應用程序 一、最終演示效果 QtCmd 不是因為它是 Qt 的組件&#xff0c;而是采用 Qt 開發了一個類似 Windows 命令提示符或者 Linux 命令行終端的應用程序&#xff0c;故取名為 QtCmd。 上述演示…