01.13 天天用的spring框架,你可能根本沒有弄明白其底層的原理

什麼是aop

AOP(Aspect-OrientedProgramming,面向方面編程),可以說是OOP(Object-Oriented Programing,面向對象編程)的補充和完善。OOP允許你定義從上到下的關係,但並不適合定義從左到右的關係。例如日誌功能。日誌代碼往往水平地散佈在所有對象層次中,而與它所散佈到的對象的核心功能毫無關係。這種散佈在各處的無關的代碼被稱為橫切(cross-cutting)代碼,在OOP設計中,它導致了大量代碼的重複,而不利於各個模塊的重用。

天天用的spring框架,你可能根本沒有弄明白其底層的原理

而AOP技術則恰恰相反,它利用一種稱為“橫切”的技術,剖解開封裝的對象內部,並將那些影響了多個類的公共行為封裝到一個可重用模塊,並將其名為“Aspect”,即方面。所謂“方面”,簡單地說,就是將那些與業務無關,卻為業務模塊所共同調用的邏輯或責任封裝起來,便於減少系統的重複代碼,降低模塊間的耦合度,並有利於未來的可操作性和可維護性。

aop使用場景

aop框架種類

  • AspectJ
  • JBoss AOP
  • Spring AOP

使用aop可以做的事情有很多。

  • 性能監控,在方法調用前後記錄調用時間,方法執行太長或超時報警。
  • 緩存代理,緩存某方法的返回值,下次執行該方法時,直接從緩存裡獲取。
  • 軟件破解,使用AOP修改軟件的驗證類的判斷邏輯。
  • 記錄日誌,在方法執行前後記錄系統日誌。
  • 工作流系統,工作流系統需要將業務代碼和流程引擎代碼混合在一起執行,那麼我們可以使用AOP將其分離,並動態掛接業務。
  • 權限驗證,方法執行前驗證是否有權限執行當前方法,沒有則拋出沒有權限執行異常,由業務代碼捕捉。

觀察一下傳統編碼方式與使用aop的區別

天天用的spring框架,你可能根本沒有弄明白其底層的原理

核心概念

描述AOP常用的一些術語有通知(Adivce)、切點(Pointcut)、連接點(Join point)、切面(Aspect)、引入(Introduction)、織入(Weaving)、通知(Advice)等。

天天用的spring框架,你可能根本沒有弄明白其底層的原理

簡單例子

相比xml配置,基於註解的方式更加簡潔方便。

@Aspect

public class TransactionDemo {

@Pointcut(value="execution(* com.yangxin.core.service.*.*.*(..))")

public void point(){

}

@Before(value="point()")

public void before(){

System.out.println("transaction begin");

}

@AfterReturning(value = "point()")

public void after(){

System.out.println("transaction commit");

}

@Around("point()")

public void around(ProceedingJoinPoint joinPoint) throws Throwable{

System.out.println("transaction begin");

joinPoint.proceed();

System.out.println("transaction commit");

}

}

在applicationContext.xml中配置。

<aspectj-autoproxy>

<bean>

spring aop原理

通過前面介紹可以知道:AOP 代理其實是由 AOP 框架動態生成的一個對象,該對象可作為目標對象使用。AOP 代理包含了目標對象的全部方法,但 AOP 代理中的方法與目標對象的方法存在差異:AOP 方法在特定切入點添加了增強處理,並回調了目標對象的方法。

天天用的spring框架,你可能根本沒有弄明白其底層的原理

Spring 的 AOP 代理由 Spring 的 IoC 容器負責生成、管理,其依賴關係也由 IoC 容器負責管理。因此,AOP 代理可以直接使用容器中的其他 Bean 實例作為目標,這種關係可由 IoC 容器的依賴注入提供。

aop開發時,其中需要程序員參與的只有 3 個部分:

  • 定義普通業務組件。
  • 定義切入點,一個切入點可能橫切多個業務組件。
  • 定義增強處理,增強處理就是在 AOP 框架為普通業務組件織入的處理動作。

為了理清關係,先來個類關係圖。

天天用的spring框架,你可能根本沒有弄明白其底層的原理

兩種動態代理方式

Spring默認採取的動態代理機制實現AOP,當動態代理不可用時(代理類無接口)會使用CGlib機制。

Spring提供了兩種方式來生成代理對象: JDKProxy和Cglib,具體使用哪種方式生成由AopProxyFactory根據AdvisedSupport對象的配置來決定。默認的策略是如果目標類是接口,則使用JDK動態代理技術,否則使用Cglib來生成代理。

JDK動態代理

  • JDK動態代理主要涉及到java.lang.reflect包中的兩個類:Proxy和InvocationHandler。InvocationHandler是一個接口,通過實現該接口定義橫切邏輯,並通過反射機制調用目標類的代碼,動態將橫切邏輯和業務邏輯編制在一起。
  • Proxy利用InvocationHandler動態創建一個符合某一接口的實例,生成目標類的代理對象。

CGLib動態代理

  • CGLib全稱為Code Generation Library,是一個強大的高性能,高質量的代碼生成類庫,可以在運行期擴展Java類與實現Java接口,CGLib封裝了asm,可以再運行期動態生成新的class。和JDK動態代理相比較:JDK創建代理有一個限制,就是隻能為接口創建代理實例,而對於沒有通過接口定義業務方法的類,則可以通過CGLib創建動態代理。

知識拓展

通過上面的分析,大家是否有種熟悉的感覺,似乎和攔截器、過濾器的功能相似。那麼問題來了,aop與攔截器、過濾器是什麼關係。

先來回顧一下攔截器與過濾器。如下圖一網友的測試,在web.xml中註冊了TestFilter1和TestFilter2。然後在spring的配置文件中配置了BaseInterceptor和TestInterceptor。得到的結果如下圖所示。從圖中可以看出,攔截器和過濾器都橫切了業務方法,看似符合aop的思想。

天天用的spring框架,你可能根本沒有弄明白其底層的原理

Filter過濾器:攔截web訪問url地址。 Interceptor攔截器:攔截以 .action結尾的url,攔截Action的訪問。 Spring AOP攔截器:只能攔截Spring管理Bean的訪問(業務層Service)

天天用的spring框架,你可能根本沒有弄明白其底層的原理

寫在最後,希望文章對在java開發路上的你,有些幫助!

下篇文章將會寫Spring cache的內容,同樣以思維導圖的方式編寫。可視化學習,讓java不再難懂。

碼農三哥,一名普通程序員,會點java軟件開發,對AI人工智能有點興趣,後續會每日分享些關於互聯網技術方面的文章,感興趣的朋友可以關注我,一起交流學習。

想轉型或剛步入程序員Java開發的朋友,有問題可以留言或私信我。

再次感謝你的閱讀!


分享到:


相關文章: