<form id="dlljd"></form>
        <address id="dlljd"><address id="dlljd"><listing id="dlljd"></listing></address></address>

        <em id="dlljd"><form id="dlljd"></form></em>

          <address id="dlljd"></address>
            <noframes id="dlljd">

              聯系我們 - 廣告服務 - 聯系電話:
              您的當前位置: > 關注 > > 正文

              Spring之AOP|使用場景、原理、配置、使用方式

              來源:CSDN 時間:2023-02-17 09:12:23

              原文網址:Spring之AOP系列--使用場景/原理_IT利刃出鞘的博客-CSDN博客

              簡介

              本文介紹Spring AOP的使用場景、原理、配置、使用方式。


              (資料圖片僅供參考)

              AOP使用場景

              Spring AOP解決了什么問題?

              問題使用SpringAOP之后

              除了核心邏輯,還要關注非核心邏輯把非核心業務封裝起來,只寫核心業務即可

              代碼重復率高(比如輸出同樣的日志格式)公共非核心的封裝起來,格式在公共部分給出即可。

              使用場景

              權限管理、異常處理、操作日志、事務控制。

              實際項目中AOP的用法

              權限管理 情景1:控制用戶的功能權限 方案詳述:在@ControllerAdvice里邊,處理全局請求,控制權限。權限管理的其他方案:(除了AOP之外的方案) 在過濾器或者攔截器中處理使用Shiro中間件異常處理 情景1:在@ControllerAdvice里邊,處理全局異常情景2:將Dubbo接口作為切面,統一處理Dubbo接口里邊的異常操作日志 情景1:按產品的需求,有的接口需要記錄操作日志 自定義注解,需要記錄操作日志的,則在Controller的方法上加此注解AOP中判斷,如果有這個自定義注解,則將參數異步寫到日志數據庫將數據同步到ES 情景1:增刪改數據時,同時要處理MySQL和ES 將相關類作為切面,若數據庫提交,則寫到ES;若回滾,則不寫到ES事務控制 情景1:使用Spring的@Transactional

              AOP有哪幾種通知,如果方法執行失敗,哪個通知不會執行?

              前置,后置,環繞,返回,異常。失敗后,返回不會執行(即使失敗,后置也會執行)。

              AOP原理(實現方式)

              Spring AOP的動態代理主要有兩種方式實現,JDK動態代理和cglib動態代理。 見:Java設計模式--代理模式--靜態代理/動態代理--使用/詳解/實例_IT利刃出鞘的博客-CSDN博客

              項JDK動態代理cglib動態代理

              類名java.lang.reflect.InvocationHandlerorg.springframework.cglib.proxy包下的原生接口源自cglib庫。

              方法攔截器public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;org.springframework.cglib.proxy.Callback、 org.springframework.cglib.proxy.MethodInterceptor

              public interface MethodInterceptor extends Callback {Object intercept(Object obj, Method m, Object[] args, MethodProxy mp) throws Throwable }

              調用方法method.invoke(Object, args)

              該動態代理是基于接口的動態代理,所以并沒有一個原始方法的調用過程,整個方法都是被攔截的。調用其他同類對象的原方法:mp.invoke(Object obj, Object[] args)

              調用原始(父類)方法:mp.invokeSuper(Object obj, Object[] args)

              SpringBoot對AOP的配置

              簡介

              如果引入的是spring-aop包,則需要使用@EnableAspectJAutoProxy開啟aop功能;如果引入的是spring-boot-starter-aop,則AOP就直接可以用了,無需加注解之類的開啟它。

              對于SpringBoot

              spring-boot-starter-aop  (此包里包含了spring-aop與aspectjweaver)

              對于Spring

              spring-aop:AOP核心功能,例如代理工廠等等aspectjweaver:支持切入點表達式、aop相關注解等。(本依賴包含aspectjrt) aspectjrt:支持aop相關注解等。

              AOP的啟用

              導入包即可,默認開啟:spring.aop.auto=true  //等價于@EnableAspectJAutoProxy

              JDK代理與CGLIB代理

              SpringBoot 1.5.x:默認使用JDK代理,即:spring.aop.proxy-target-class=false  若設置為true,則使用CGLIB動態代理。 SpringBoot 2.x:默認使用CGLIB代理,即:spring.aop.proxy-target-class=true。

              對應的自動配置類為:org.springframework.boot.autoconfigure.aop.AopAutoConfiguration

              為什么SpringBoot 2.x:默認使用CGLIB代理?

              見spring的issue:https://github.com/spring-projects/spring-boot/issues/5423

              即:我們應該使用@EnableTransactionManagement(proxyTargetClass = true)來防止人們不使用接口時出現討厭的代理問題。

              討厭的代理問題

              假設,我們有一個UserServiceImpl和UserService類,此時需要在UserContoller中使用UserService。在 Spring 中通常都習慣這樣寫代碼:

              @AutowiredUserService userService;

              在這種情況下,無論是使用 JDK 動態代理,還是 CGLIB 都不會出現問題。

              但是,如果你的代碼是這樣的呢:

              @AutowiredUserServiceImpl userService;

              這個時候,如果我們是使用 JDK 動態代理,那在啟動時就會報錯:

              SpringAOP與 Aspectj

              注意

              SpringAOP功能已經基本夠用了,除非要在接口上動態代理或者方法攔截精確到getter和setter。這些奇葩的需求,一般不使用Aspectj。

              問題:既然一般用不到Aspectj,為什么都要引入Aspectjweaver包?

              答案

              SpringAOP如果使用xml來配置,是不需要引入Aspectjweaver包的。項目中引入Aspectjweaver包僅僅是為了使用它的注解和切入點表達式。SpringAOP在運行時,用的核心功能是它自己的那一套(動態代理),與Aspectj的編譯器或者織入器無任何關系。

              無論是使用spring aop還是 aspectj都需要aspectjweaver.jar spring-aop.jar這兩個jar包。

              簡介

              項Spring AOPAspectJ

              織入時機只能運行時織入。支持編譯時、編譯后和加載時織入。不支持運行時織入

              原理代理由目標對象創建的, 且切面應用在這些代理上運行前織入。

              性能比 AspectJ 慢多了更好的性能

              切入(編織)位置僅支持方法切入點。且只匹配public方法支持所有切入點:

              public, protected, private皆可。

              字段、方法、構造函數、靜態初始值設定項、最終類/方法等皆可

              管理的類只能在由 Spring 容器管理的 bean 上實現可在所有域對象上實現

              編程語言在純 Java 中實現使用 Java 編程語言的擴展實現。

              目標

              Spring aop 旨在提供一個跨 Spring IoC 的簡單的 aop 實現, 以解決程序員面臨的最常見問題。它不打算作為一個完整的 AOP 解決方案 —— 它只能應用于由 Spring 容器管理的 bean

              AspectJ 是原始的 aop 技術, 目的是提供完整的 aop 解決方案。它更健壯, 但也比 Spring AOP 復雜得多。還值得注意的是, AspectJ 可以在所有域對象中應用。

              織入

              AspectJ 和 Spring AOP 都使用不同類型的編織, 這會影響它們在性能和易用性方面的行為。

              AspectJ 使用三種不同類型的Weaving: 1.編譯時 Weaving: AspectJ 編譯器作為輸入我們的方面的源代碼和我們的應用, 并產生一個織入類文件作為輸出; 2.編譯后 Weaving: 這也稱為二進制織入。它是用來織入現有的類文件和 JAR 文件與我們的方面; 3.加載時間 Weaving: 這就像前二進制織入, 不同的是織入被推遲, 直到類加載程序加載類文件到 JVM。

              內部結構與應用

              Spring aop 是基于代理的 aop 框架。這意味著, 要實現目標對象的各個方面, 它將創建該對象的代理。使用以下兩種方法之一實現: 1.JDK 動態代理 —— Spring AOP 的首選方式。只要目標對象實現甚至一個接口, 就會使用 JDK 動態代理; 2.CGLIB 代理 —— 如果目標對象沒有實現接口, 則可以使用 CGLIB 代理。 我們可以從 官方文檔 中了解有關 Spring AOP 代理機制的更多信息。

              AspectJ 在運行時不做任何事情, 因為類是直接用方面進行編譯的。 與 Spring AOP 不同, 它不需要任何設計模式。為了編織代碼的各個方面, 它引入了稱為 AspectJ 編譯器 (ajc) 的編譯器, 通過它編譯我們的程序, 然后通過提供一個小型 (100K) 運行時庫來運行它。

              joinpoints

              Spring AOP 是基于代理模式的。因此, 它需要將目標 Java 類分類, 并相應地應用交叉問題。但這是有限制的。我們不能在 "最終" 類中應用交叉問題 (或方面), 因為它們不能被重寫, 因此會導致運行時異常。同樣適用于靜態和最終方法。不能將 Spring 方面應用于它們, 因為它們不能被覆蓋。因此, 由于這些限制, Spring AOP 只支持方法執行連接點。

              AspectJ 在運行前直接將橫切關注點編織到實際代碼中。與 Spring AOP 不同, 它不需要對目標對象進行子類, 因此也支持許多其他 joinpoints。

              支持的 joinpoints 的摘要:

              JoinpointSpring AOP SupportedAspectJ Supported

              Method CallNoYes

              Method ExecutionYesYes

              Constructor CallNoYes

              Constructor ExecutionNoYes

              Static initializer executionNoYes

              Object initializationNoYes

              Field referenceNoYes

              Field assignmentNoYes

              Handler executionNoYes

              Advice executionNoYes

              簡單性

              Spring AOP 顯然更簡單, 因為它不會在我們的構建過程中引入任何額外的編譯器或織入。它使用運行時編織, 因此它與我們通常的構建過程無縫集成。雖然它看起來很簡單, 但它只適用于由 Spring 管理的 bean。

              AspectJ:我們需要引入 AspectJ 編譯器 (ajc) 并重新打包所有的庫 (除非我們切換到編譯后或加載時間的織入)。當然,,這比前者更復雜,,因為它引入了 AspectJ Java 工具 (包括編譯器 (ajc)、調試器 (ajdb)、文檔生成器 (ajdoc)、程序結構瀏覽器 (ajbrowser)),我們需要將它們與我們的 IDE 或構建工具集成。

              性能

              就性能而言,,編譯時織入比運行時織入快得多。

              Spring AOP 是基于代理的框架, 因此在應用程序啟動時會創建代理。另外, 每個方面還有一些方法調用, 這會對性能產生負面影響。

              AspectJ 在應用程序執行之前將這些方面編織到主代碼中, 因此沒有額外的運行時開銷, 與 Spring AOP 不同。

              基于這些原因,,AspectJ 的速度幾乎比 Spring AOP 快8到35倍。

              這兩個框架是完全兼容的。 我們可以隨時利用Spring AOP,并且仍然使用AspectJ來獲得前者不支持的連接點。

              其他網址

              原理

              Java設計模式--靜態代理與動態代理_IT利刃出鞘的博客-CSDN博客Spring中的AOP原理_Java_ChaunceyChen的博客-CSDN博客Spring AOP實現原理_Java_yanweihpu的博客-CSDN博客

              實現方式

              springCloud AOP功能實現 - 塵敘緣的個人空間 - OSCHINA - 中文開源技術交流社區

              Spring 5 AOP 默認改用 CGLIB 了?從現象到源碼的深度分析 - 云+社區 - 騰訊云

              責任編輯:

              標簽:

              相關推薦:

              精彩放送:

              新聞聚焦
              Top 中文字幕在线观看亚洲日韩