① 2020-07-26 帶著疑問看源碼 -- springboot aop默認採用什麼動態代理機制
了解springboot aop的動態代理方式有哪些種類?
有3種,前提均開啟spring.aop.auto=true:
1. jdk動態代理:當spring.aop.proxy-target-class=false, 引入了aspectjweaver依賴時生效
2. cglib代理:當spring.aop.proxy-target-class=true, 引入了aspectjweaver依賴時生效
3. 基礎代理:當spring.aop.proxy-target-class=true, 若沒有aspectjweaver依賴時生效,只作用於框架內部的advisors,
我們既然用springboot那麼就採用springboot的AopAutoConfiguration自動配置類來載入aop機制的,內部對@EnableAspectJAutoProxy進行了封裝,擴展了一些配置項,同時還提供了ClassProxyingConfiguration配置(下面會講到).
這個自動裝配類會是spring boot框架自動會裝配的,所以說默認aop機制是打開的,可以通過配置項:spring.aop.auto=false 手工關閉。
這個配置類會根據spring.aop.proxy-target-class配置項來決定採用jdk動態代理或者cglib動態代理:
注意:配置類生效前提是@ConditionalOnClass(Advice.class),說明只有當引入了依賴項才生效:
而這里推薦使用spring-boot-starter-aop來傳遞依賴:
這里我們已經看到提供了原生spring的兩種代理方式,接著看AopAutoConfiguration源碼發現還有個ClassProxyingConfiguration配置類,其生效條件之一是@ConditionalOnMissingClass("org.aspectj.weaver.Advice"),就是當項目里沒有aspectjweaver的依賴的時候生效。
我們進入AopConfigUtils.(registry)方法,通過幾步調用跳轉:
發現會去注冊後置處理器,查看源碼注釋:
表明了只為基礎的advisor做動態代理,而忽略應用定義的Advisors,說明項目中我們自定義的切面是不會被AOP代理的。
② spring cglib代理耗時太久
由於整個Spring載入和實例化bean的過程原因導致。
Spring的bean的scope設置成prototype,就是每次都要創建一個實例,可以看一下Spring的源碼,創建一個Spring實例是很復雜的一個過程,CGlib代理只是其中的一步,底層也是通過反射完成的,耗時的關鍵不在CGlib代理,而是在整個Spring載入和實例化bean的過程。
CGlib是屬於動態管理,動態代理是在不改變原有代碼的情況下上進行對象功能增強,使用代理對象代替原來的對象完成功能,進而達到拓展功能的目的。