1. 程式人生 > >面試題: 面向切面程式設計(AOP)的理解

面試題: 面向切面程式設計(AOP)的理解

AOP是什麼?

    AOP的全稱是Aspect Orient Programming,即面向切面程式設計。是對OOP(Object Orient Programming)的一種補充,戰門用於處理一些具有橫切性質的服務。常常用於日誌輸出、安全控制等。

       上面說到是對OOP的一種補充,具體補充的是什麼呢?考慮一種情況,如果我們需要在所有方法執行前列印一句日誌,按照OOP的處理思想,我們需要在每個業務方法開始時加入一些語句,但是我們辛辛苦苦加完之後,如果又要求在這句日誌列印後再列印一句,那是不是又要加一遍?這時候你一定會想到,在某個類中編寫一個日誌列印方法,該方法執行這些日誌列印操作,然後在每個業務方法之前加入這句方法呼叫,這就是面向物件程式設計思想。但是如果要求我們在業務方法結束時再列印一些日誌呢,是不是還要去每個業務方法結束時加一遍?這樣始終不是辦法,而且我們總是在改業務方法,在業務方法裡面摻雜了太多的其他操作,侵入性太高。

       這時候AOP就起到作用了,我們可以編寫一個切面類(Aspect),在其中的方法中來編寫橫切邏輯(如列印日誌),然後通過配置或者註解的方式來宣告該橫切邏輯起作用的位置。

 

總結:aop就是寫程式碼的時候 把各個模組中需要重複寫的抽取出來,弄成一個切面。例如日誌,許可權。

切面的具體表現就是實現公共方法的類

通知:在實際應用中通常是切面類中的一個方法

在傳統的編寫業務邏輯處理程式碼時,我們通常會習慣性地做幾件事情:日誌記錄、事務控制及許可權控制等,然後才是編寫核心的業務邏輯處理程式碼。當代碼編寫完成回頭再看時,不禁發現,揚揚灑灑上百行程式碼中,真正用於核心業務邏輯處理才那麼幾行,如圖6-4所示。方法複方法,類復類,就這樣子帶著無可奈何遺憾地度過了多少個春秋。這倒也罷,倘若到了專案的尾聲,突然決定在許可權控制上需要進行大的變動時,成千上萬個方法又得一一"登門拜訪",痛苦"雪上加霜"。

如果能把圖6-4中眾多方法中的所有共有程式碼全部抽取出來,放置到某個地方集中管理,然後在具體執行時,再由容器動態織入這些共有程式碼的話,最起碼可以解決兩個問題:

Java EE程式設計師在編寫具體的業務邏輯處理方法時,只需關心核心的業務邏輯處理,既提高了工作效率,又使程式碼變更簡潔優雅。

在日後的維護中由於業務邏輯程式碼與共有程式碼分開存放,而且共有程式碼是集中存放的,因此使維護工作變得簡單輕鬆。

面向切面程式設計AOP技術就是為解決這個問題而誕生的,切面就是橫切面,如圖6-5所示,代表的是一個普遍存在的共有功能,例如,日誌切面、許可權切面及事務切面等。

下面我們以使用者管理業務邏輯元件UserService的AOP實現過程(見圖6-6)為例,深度剖析一下AOP技術的實現原理。AOP技術是建立在Java語言的反射機制與動態代理機制之上的。業務邏輯元件在執行過程中,AOP容器會動態建立一個代理物件供使用者呼叫,該代理物件已經按Java EE程式設計師的意圖將切面成功切入到目標方法的連線點上,從而使切面的功能與業務邏輯的功能同時得以執行。從原理上講,呼叫者直接呼叫的其實是AOP容器動態生成的代理物件,再由代理物件呼叫目標物件完成原始的業務邏輯處理,而代理物件則已經將切面與業務邏輯方法進行了合成。

現將圖6-6中涉及到的一些概念解釋如下。

切面(Aspect):其實就是共有功能的實現。如日誌切面、許可權切面、事務切面等。在實際應用中通常是一個存放共有功能實現的普通Java類,之所以能被AOP容器識別成切面,是在配置中指定的。

通知(Advice):是切面的具體實現。以目標方法為參照點,根據放置的地方不同,可分為前置通知(Before)、後置通知(AfterReturning)、異常通知(AfterThrowing)、最終通知(After)與環繞通知(Around)5種。在實際應用中通常是切面類中的一個方法,具體屬於哪類通知,同樣是在配置中指定的。

連線點(Joinpoint):就是程式在執行過程中能夠插入切面的地點。例如,方法呼叫、異常丟擲或欄位修改等,但spring只支援方法級的連線點。

切入點(Pointcut):用於定義通知應該切入到哪些連線點上。不同的通知通常需要切入到不同的連線點上,這種精準的匹配是由切入點的正則表示式來定義的。

目標物件(Target):就是那些即將切入切面的物件,也就是那些被通知的物件。這些物件中已經只剩下乾乾淨淨的核心業務邏輯程式碼了,所有的共有功能程式碼等待AOP容器的切入。

代理物件(Proxy):將通知應用到目標物件之後被動態建立的物件。可以簡單地理解為,代理物件的功能等於目標物件的核心業務邏輯功能加上共有功能。代理物件對於使用者而言是透明的,是程式執行過程中的產物。

織入(Weaving):將切面應用到目標物件從而建立一個新的代理物件的過程。這個過程可以發生在編譯期、類裝載期及執行期,當然不同的發生點有著不同的前提條件。譬如發生在編譯期的話,就要求有一個支援這種AOP實現的特殊編譯器;發生在類裝載期,就要求有一個支援AOP實現的特殊類裝載器;只有發生在執行期,則可直接通過Java語言的反射機制與動態代理機制來動態實現。