- Spring技術(shù)內(nèi)幕:深入解析Spring架構(gòu)與設(shè)計原理(第2版)
- 計文柯
- 1584字
- 2018-12-31 19:55:44
3.2 Spring AOP的設(shè)計與實現(xiàn)
3.2.1 JVM的動態(tài)代理特性
前面已經(jīng)介紹了橫切關(guān)注點的一些概念,以及它們在Spring中的具體設(shè)計和實現(xiàn)。具體來說,在Spring AOP實現(xiàn)中,使用的核心技術(shù)是動態(tài)代理,而這種動態(tài)代理實際上是JDK的一個特性(在JDK 1.3以上的版本里,實現(xiàn)了動態(tài)代理模式)。通過JDK的動態(tài)代理特性,可以為任意Java對象創(chuàng)建代理對象,對于具體使用來說,這個特性是通過Java Reflection API來完成的。在了解具體的Java Reflection之前,先簡要地復(fù)習(xí)一下Proxy模式,其靜態(tài)類圖如圖3-9所示。

圖3-9 Proxy模式的靜態(tài)類圖
在圖3-9中,可以看到有一個RealSubject,這個對象是目標(biāo)對象,而在代理模式的設(shè)計中,會設(shè)計一個接口和目標(biāo)對象一致的代理對象Proxy,它們都實現(xiàn)了接口Subject的request方法。在這種情況下,對目標(biāo)對象的request的調(diào)用,往往就被代理對象“渾水摸魚”給攔截了,通過這種攔截,為目標(biāo)對象的方法操作做了鋪墊,所以稱之為代理模式。了解了如圖3-10所示的調(diào)用關(guān)系,就可以清楚地了解這里的過程。

圖3-10 Proxy模式的調(diào)用關(guān)系
在Proxy的調(diào)用過程中,如果客戶(Client)調(diào)用Proxy的request方法,會在調(diào)用目標(biāo)對象的request方法的前后調(diào)用一系列的處理,而這一系列的處理相對于目標(biāo)對象來說是透明的,目標(biāo)對象對這些處理可以毫不知情,這就是Proxy模式。
通過前面的介紹可以知道,JDK中已經(jīng)實現(xiàn)了這個Proxy模式,在基于Java虛擬機(jī)設(shè)計應(yīng)用程序時,只需要直接使用這個特性就可以了。具體來說,可以在Java的reflection包中看到Proxy對象,這個對象生成后,所起的作用就類似于Proxy模式中的Proxy對象。在使用時,還需要為代理對象(Proxy)設(shè)計一個回調(diào)方法,這個回調(diào)方法起到的作用是,在其中加入了作為代理需要額外處理的動作,或者說,在這個方法中,所謂額外動作,可以參考Proxy模式中的preOperation()和postOperation()方法。這個回調(diào)方法,如果在JDK中實現(xiàn),需要實現(xiàn)下面所示的InvocationHandler接口:
public interface InvocationHandler { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable; }
在這個接口方法中,只聲明了一個invoke方法,這個invoke方法的第一個參數(shù)是代理對象實例,第二個參數(shù)是Method方法對象,代表的是當(dāng)前Proxy被調(diào)用的方法,最后一個參數(shù)是被調(diào)用的方法中的參數(shù)。通過這些信息,在invoke方法實現(xiàn)中,已經(jīng)可以了解Proxy對象的調(diào)用背景了。至于怎樣讓invoke方法和Proxy掛上鉤,熟悉Proxy用法的讀者都知道,只要在實現(xiàn)通過調(diào)用Proxy.newIntance方法生成具體Proxy對象時把InvocationHandler設(shè)置到參數(shù)里面就可以了,剩下的由Java虛擬機(jī)來完成。
3.2.2 Spring AOP的設(shè)計分析
大家都知道,AOP模塊是Spring的核心模塊,雖然在Java社區(qū)里AspectJ是最完整的AOP框架,但Spring AOP也提供了另外一種實現(xiàn),這種實現(xiàn)并不是AspectJ的競爭者,相反,Spring AOP還將AspectJ集成了進(jìn)來,為IoC容器和Spring應(yīng)用開發(fā)提供了一個一致性的AOP解決方案。
Spring AOP的核心技術(shù)是上一小節(jié)介紹的JDK動態(tài)代理技術(shù)。以動態(tài)代理技術(shù)為基礎(chǔ),設(shè)計出了一系列AOP的橫切實現(xiàn),比如前置通知、返回通知、異常通知等。同時,Spring AOP還提供了一系列的Pointcut來匹配切入點,可以使用現(xiàn)有的切入點來設(shè)計橫切面,也可以擴(kuò)展相關(guān)的Pointcut方法來實現(xiàn)切入需求。
在Spring AOP中,雖然對于AOP的使用者來說,只需要配置相關(guān)的Bean定義即可,但仔細(xì)分析Spring AOP的內(nèi)部設(shè)計可以看到,為了讓AOP起作用,需要完成一系列過程,比如,需要為目標(biāo)對象建立代理對象,這個代理對象可以通過使用JDK的Proxy來完成,也可以通過第三方的類生成器CGLIB來完成。然后,還需要啟動代理對象的攔截器來完成各種橫切面的織入,這一系列的織入設(shè)計是通過一系列Adapter來實現(xiàn)的。通過一系列Adapter的設(shè)計,可以把AOP的橫切面設(shè)計和Proxy模式有機(jī)地結(jié)合起來,從而實現(xiàn)在AOP中定義好的各種織入方式。具體的設(shè)計實現(xiàn)可以參考后面的內(nèi)容,這里只是簡要介紹一下。
3.2.3 Spring AOP的應(yīng)用場景
Spring AOP為IoC的使用提供了更多的便利,一方面,應(yīng)用可以直接使用AOP的功能,設(shè)計應(yīng)用的橫切關(guān)注點,把跨越應(yīng)用程序多個模塊的功能抽象出來,并通過簡單的AOP的使用,靈活地編制到模塊中,比如可以通過AOP實現(xiàn)應(yīng)用程序中的日志功能。另一方面,在Spring內(nèi)部,一些支持模塊也是通過Spring AOP來實現(xiàn)的,比如后面將要詳細(xì)介紹的事務(wù)處理。從這兩個角度就已經(jīng)可以看到Spring AOP的核心地位了。下面以ProxyFactoryBean的實現(xiàn)為例,和大家一起來了解Spring AOP的具體設(shè)計和實現(xiàn)。
- Spring Boot 2實戰(zhàn)之旅
- Node.js+Webpack開發(fā)實戰(zhàn)
- 軟件架構(gòu)設(shè)計:大型網(wǎng)站技術(shù)架構(gòu)與業(yè)務(wù)架構(gòu)融合之道
- Git高手之路
- Oracle 18c 必須掌握的新特性:管理與實戰(zhàn)
- Node.js全程實例
- Android開發(fā)案例教程與項目實戰(zhàn)(在線實驗+在線自測)
- Python忍者秘籍
- JavaCAPS基礎(chǔ)、應(yīng)用與案例
- PHP編程基礎(chǔ)與實例教程
- Learning Node.js for .NET Developers
- SpringBoot從零開始學(xué)(視頻教學(xué)版)
- Python趣味編程與精彩實例
- ASP.NET求職寶典
- Java高手是怎樣煉成的:原理、方法與實踐