本文將為各位帶來 Spring 的另一個重點知識點 —— Spring AOP灾常。關(guān)注我的公眾號「Java面典」照激,每天 10:24 和你一起了解更多 Java 相關(guān)知識點发魄。
什么是 AOP
面向切面編程(aspect-oriented programming),是一種將橫切關(guān)注點與業(yè)務(wù)邏輯分離的編程方式俩垃。每個橫切關(guān)注點都集中在一個地方励幼,而不是分散在多處代碼中。這樣使我們的服務(wù)模塊更加簡潔口柳,因為它們只包含了主要關(guān)注點的代碼苹粟,而次要的功能或者說輔助的功能被轉(zhuǎn)移到切面中了。
AOP 主要應(yīng)用場景有:
- Authentication 權(quán)限
- Caching 緩存
- Context passing 內(nèi)容傳遞
- Error handling 錯誤處理
- Lazy loading 懶加載
- Debugging 調(diào)試
- logging, tracing, profiling and monitoring 記錄跟蹤 優(yōu)化 校準
- Performance optimization 性能優(yōu)化
- Persistence 持久化
- Resource pooling 資源池
- Synchronization 同步
- Transactions 事務(wù)
AOP 核心知識點
主要術(shù)語
- Aspect(切面):切入業(yè)務(wù)流程的一個獨立模塊跃闹,在一個應(yīng)用程序可以擁有任意數(shù)量的切面嵌削。如事務(wù)管理毛好,就是切面的一個應(yīng)用例子;
- Join point(連接點):業(yè)務(wù)流程在運行過程中需要插入切面的具體位置掷贾。如執(zhí)行某個特定方法或者處理異常的時候睛榄;
- Advice(通知):是切面的具體實現(xiàn)方法∠胨В可分為前置通知(Before)场靴、后置通知(AfterReturning)、異常通知(AfterThrowing)港准、最終通知(After)和環(huán)繞通知(Around)五種旨剥。實現(xiàn)方法具體屬于哪類通知,是在配置文件和注解中指定的浅缸;
- Pointcut(切入點):用于定義通知應(yīng)該切入到哪些連接點上轨帜,不同的通知通常需要切入到不同的連接點上;
- Target(目標對象):被一個或者多個切面所通知的對象衩椒;
- Proxy(代理對象):將通知應(yīng)用到目標對象之后被動態(tài)創(chuàng)建的對象蚌父。可以簡單地理解為毛萌,代理對象為目標對象的業(yè)務(wù)邏輯功能加上被切入的切面所形成的對象苟弛;
- Weaving(切入):將切面應(yīng)用到目標對象從而創(chuàng)建一個新的代理對象的過程。這個過程可以發(fā)生在編譯期阁将、類裝載期及運行期膏秫。
通知類型
Spring AOP 主要有五種通知類型,分別是前置通知(Before)做盅、后置通知(AfterReturning)缤削、異常通知(AfterThrowing)、最終通知(After)和環(huán)繞通知(Around):
- Before(前置通知):在連接點之前執(zhí)行的通知吹榴,但這個通知不能阻止連接點之前的執(zhí)行流程(除非它拋出一個異常)亭敢;
- AfterReturning(后置通知):在連接點正常執(zhí)行完成之后的通知;
- AfterThrowing(異常通知):在連接點方法拋出異常時執(zhí)行的通知图筹;
- After(最終通知):在連接點執(zhí)行完成之后的通知(無論是正常完成帅刀,還是拋出異常退出執(zhí)行);
- Around(環(huán)繞通知):可以在連接點執(zhí)行前后都執(zhí)行的通知婿斥。
AOP 的兩種代理方式
Spring 提供了兩種方式來生成代理對象: JDKProxy 和 Cglib,具體使用哪種方式生成由 AopProxyFactory 根據(jù) AdvisedSupport 對象的配置來決定哨鸭。默認的策略是如果目標類是接口民宿,則使用 JDK 動態(tài)代理技術(shù),否則使用 Cglib 來生成代理像鸡。
JDK 動態(tài)接口代理
JDK 動態(tài)代理主要涉及到 java.lang.reflect 包中的兩個類:Proxy 和 InvocationHandler活鹰。InvocationHandler是一個接口哈恰,通過實現(xiàn)該接口定義橫切邏輯,并通過反射機制調(diào)用目標類的代碼志群,動態(tài)將橫切邏輯和業(yè)務(wù)邏輯編制在一起着绷。Proxy 利用 InvocationHandler 動態(tài)創(chuàng)建一個符合某一接口的實例,生成目標類的代理對象锌云。
CGLib 動態(tài)代理
CGLib 全稱為 Code Generation Library荠医,是一個強大的高性能,高質(zhì)量的代碼生成類庫桑涎,可以在運行期擴展 Java 類與實現(xiàn) Java 接口彬向,CGLib 封裝了 asm,可以再運行期動態(tài)生成新的 class攻冷。和 JDK 動態(tài)代理相比較:JDK 創(chuàng)建代理有一個限制娃胆,就是只能為接口創(chuàng)建代理實例,而對于沒有通過接口定義業(yè)務(wù)方法的類等曼,則可以通過 CGLib 創(chuàng)建動態(tài)代理里烦。