什麼是aop
AOP(Aspect-OrientedProgramming,面向方面編程),可以說是OOP(Object-Oriented Programing,面向對象編程)的補充和完善。OOP允許你定義從上到下的關係,但並不適合定義從左到右的關係。例如日誌功能。日誌代碼往往水平地散佈在所有對象層次中,而與它所散佈到的對象的核心功能毫無關係。這種散佈在各處的無關的代碼被稱為橫切(cross-cutting)代碼,在OOP設計中,它導致了大量代碼的重複,而不利於各個模塊的重用。
而AOP技術則恰恰相反,它利用一種稱為“橫切”的技術,剖解開封裝的對象內部,並將那些影響了多個類的公共行為封裝到一個可重用模塊,並將其名為“Aspect”,即方面。所謂“方面”,簡單地說,就是將那些與業務無關,卻為業務模塊所共同調用的邏輯或責任封裝起來,便於減少系統的重複代碼,降低模塊間的耦合度,並有利於未來的可操作性和可維護性。
aop使用場景
aop框架種類
- AspectJ
- JBoss AOP
- Spring AOP
使用aop可以做的事情有很多。
- 性能監控,在方法調用前後記錄調用時間,方法執行太長或超時報警。
- 緩存代理,緩存某方法的返回值,下次執行該方法時,直接從緩存裡獲取。
- 軟件破解,使用AOP修改軟件的驗證類的判斷邏輯。
- 記錄日誌,在方法執行前後記錄系統日誌。
- 工作流系統,工作流系統需要將業務代碼和流程引擎代碼混合在一起執行,那麼我們可以使用AOP將其分離,並動態掛接業務。
- 權限驗證,方法執行前驗證是否有權限執行當前方法,沒有則拋出沒有權限執行異常,由業務代碼捕捉。
觀察一下傳統編碼方式與使用aop的區別
核心概念
描述AOP常用的一些術語有通知(Adivce)、切點(Pointcut)、連接點(Join point)、切面(Aspect)、引入(Introduction)、織入(Weaving)、通知(Advice)等。
簡單例子
相比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 的 AOP 代理由 Spring 的 IoC 容器負責生成、管理,其依賴關係也由 IoC 容器負責管理。因此,AOP 代理可以直接使用容器中的其他 Bean 實例作為目標,這種關係可由 IoC 容器的依賴注入提供。
aop開發時,其中需要程序員參與的只有 3 個部分:
- 定義普通業務組件。
- 定義切入點,一個切入點可能橫切多個業務組件。
- 定義增強處理,增強處理就是在 AOP 框架為普通業務組件織入的處理動作。
為了理清關係,先來個類關係圖。
兩種動態代理方式
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的思想。
Filter過濾器:攔截web訪問url地址。 Interceptor攔截器:攔截以 .action結尾的url,攔截Action的訪問。 Spring AOP攔截器:只能攔截Spring管理Bean的訪問(業務層Service)
寫在最後,希望文章對在java開發路上的你,有些幫助!
下篇文章將會寫Spring cache的內容,同樣以思維導圖的方式編寫。可視化學習,讓java不再難懂。
碼農三哥,一名普通程序員,會點java軟件開發,對AI人工智能有點興趣,後續會每日分享些關於互聯網技術方面的文章,感興趣的朋友可以關注我,一起交流學習。
想轉型或剛步入程序員Java開發的朋友,有問題可以留言或私信我。
再次感謝你的閱讀!
閱讀更多 碼農三哥 的文章