AOP技術應用和研究--AOP簡單應用
為了更好的理解AOP實踐和體現AOP的優勢,我們始終將OOP和AOP的比較貫穿到下文中。並在最終總結出AOP與OOP相比所擁有的優點,AOP的缺點以及AOP一般的使用場景。
1.1 問題空間到解空間的對映
在比較研究OOP和AOP實踐之前,先讓解決從理論上OOP和AOP解決問題的差別,也就是它們各自從問題空間到解空間的不同對映關係。
1.1.1“問題空間”和“解空間”的定義
在不同的文獻中對其定義有著細微的差別,本文對其定義的如下:
問題空間(problemspace)是相對於解的領域內,對問題的分析和抽象所形成的領域。
解空間(solutionspace)
軟體開發總是為了解決某一個或某一組特定的問題,從需求出發產生一個能滿足需求的軟體,就等於得到了問題的解,因此它可以粗略地抽象成有問題空間到解空間的對映的過程。那麼需求分析自然屬於問題空間,我們把系統分析,設計模型和程式歸為解空間。問題空間到解空間的對映不同,這是AOP和OOP的根本區別。
1.1.2 OOP中的問題空間到解空間的對映
將問題空間向解空間對映時採用的是多維到一維的對映。OOP使我們可以把系統看做是一批相互合作的物件。類允許我們把實現細節隱藏在介面下。多型性為相關概念提供公共的行為和介面,並允許特定的組建在無需訪問基礎實現的前提下改變特定的行為。但OOP技術將問題世界裡的自然界對映成的基本單位是“類”,一個類實現一個介面後,那就不能動態地實現另一個介面,已有類的行為在編譯以前就基本固定,要麼是類內部定義的方法,要麼是繼承和實現介面繼承過來的方法。但是實際的程式設計工作中我們碰到了“交叉類”的情況,即橫切關注點。
1.1.3AOP中的問題空間到解空間的對映
AOP能夠比OOP更好的分離系統關注點,從而提供模組化的橫切關注點。可以把一個複雜的系統看作是由多個關注點來組合實現的。一個典型的系統可能會包括幾個方面的關注點,如業務邏輯,效能,資料儲存,日誌和排程資訊,授權,安全,執行緒,錯誤檢查等,還有開發過程中的關注點,如易懂,易維護,易追查,易擴充套件等,這樣就完成了多維到多維的對映過程(如圖4.1)
1.1.4針對的問題
OOP針對業務處理過程的實體及其屬性和行為進行抽象封裝,以獲得更加清晰高效的邏輯單元劃分。面向名詞領域,關注的是縱向的,表示物件之間的泛華-特化的關係(通過繼承來實現),其一般關注點的實現單元是類。
AOP則是針對業務處理過程中的切面進行提取,它所面對的是處理過程中的某一個步驟或者階段,已獲得邏輯過程中各部分之間低耦合性的隔離效果。面向動詞領域,關注的是橫向的。就是邏輯過程中某個片段或切面,比如:日誌管理,許可權管理等。它所關注的等多地是一些軟體系統本身的東西。而不是面向物件中多關注的業務邏輯。用同一種鬆散的方式來降低系統之間的耦合度等問題,其模組化單位是切面。
2 AOP的開發步驟
AOP,從其本質上講,就是用一種鬆散耦合的方式來實現各個獨立的關注點,然後再組合這些實現來建立最終的系統。用它所建立的系統是鬆散耦合的。我們通過上面分析基於AOP問題空間到解空間以及2AOP簡介我們總結出AOP軟體開發的一般步驟,如圖4.2所示,需要以下三個步驟[18]:(具體例子見4.3)
(1) 關注點分解。通過分析使用者需求,提取出模組級的核心業務關注點和系統將級的橫切關注點。在這一步裡,需要把核心關注點同系統級的橫切關注點分開。橫切關注點的劃分通常滿足以下幾個條件:
l 關注點所實現的功能橫跨了多個模組
l 關注點與核心業務相對獨立,不屬於同一問題域
l 關注點不屬於系統的業務功能範疇
(2) 關注點實現。對於核心業務邏輯關注點,通過OOP的方法來實現,生成各個類;面對於橫切關注點,要通過AOP的方法來實現,生成方面程式碼。
(3)關注點重組。重組的過程也叫織入或編織(織入的方法見),就是利用一定的重組規則,通過方面編織器把方面程式碼編織到基於00P實現的核心功能程式碼當中。以構建最終系統。3 一個實際場景
我們在幾乎任何一個B/S模式的系統開發中,都會遇到登入這麼一個模組。很簡單,使用者登入的過程,涉及到對使用者的登入認證,看使用者輸入的使用者名稱和密碼是否合法。下面我們將用OOP和AOP兩種方式來實現登入模組。在中實現方式的比較中,將得到OOP和AOP的區別,AOP開發的一般步驟,並且分析AOP技術的適用的場景以及AOP技術使用給我們系統開發帶來的優點。
4 OOP實現
使用Transaction類來模擬事物管理,程式碼如下:
public class Transaction {
//模擬開啟事務
public void beginTransaction() {
System.out.println("開啟事務");
}
//模擬提交事務
public void commit(){
System.out.println("提交事務");
}
}
使用Login類來模擬登入這個業務,程式碼如下:
public class Login {
private Transaction transaction;
//模擬使用者登入
public Login(Transaction transaction) {
this.transaction = transaction;
}
//模擬登入這個業務操作
public void login() {
transaction.beginTransaction();
System.out.println(“驗證使用者名稱和密碼是否合法”)
transaction.commit();
}
}
4.1測試
使用Client來模擬客戶端使用者觸發登入事件,程式碼如下:
public class Client {
//模擬客戶端使用者觸發登入事件
@Test
public void testLogin() {
Transaction transaction = new Transaction();
Login login = new Login(transaction);
login.login();
}
}
4.2需求變更
上面是我們登入的這模組的一個簡單的模擬實現,加入有一天由於公司的需要我們將對每一次使用者的登入做日誌記錄,方便今後做安全審計。當然軟體系統的變化是無常,這種假設也完全是有可能。我們雖然可以通過科學的需求來儘量的避免這種情況,但是完全避免是不可能的。好的,我們現在要在登入中加入日誌處理的功能。
使用Logger類來模擬日誌處理功能,程式碼如下:
public class Logger {
public void logging() {
System.out.println("logging");
}
}
但是我們很快發現Login類也必須做出改變如下:
public class Login {
private Transaction transaction;
//增加logger
Private Logger logger;
//模擬使用者登入
public Login(Logger logger,Transaction transaction) {
this.logger = logger ;
this.transaction = transaction;
}
//模擬登入這個業務操作
public void login(String username, String password) {
transaction.beginTransaction();
System.out.println(“驗證使用者名稱和密碼是否合法”);
logger.logging();
transaction.commit();
}
}
5 SpringAOP實現
我們按照2AOP開發步驟來使用Spring AOP來實現上面的例子。
5.1 關注點分解
通過分析我們可以得出在登入模組中,我們要實現的核心業務功能是登入,它是我們的核心業務功能。按照4.2AOP開發步驟橫切關注點的劃分通常滿足以下幾個條件。我們不難發現事務處理和日誌處理並不屬於核心業務功能,而且可能橫跨其他的模組。所以事務處理和日誌處理是橫切關注點。具體實現如下:
5.2關注點實現
按照Spring AOP的語言規範,Transaction類來模擬事物管理切面,程式碼同3.4OOP實現的Transaction。Logger類來模擬日誌處理切面,程式碼同3.4OOP實現的Logger。其中Transaction和Logger就是AOP中的切面,beginTransaction() ,commit()和logging()方法就是AOP中的通知。
核心業務關注點實現:
public class Login {
//模擬登入這個業務操作
public void login() {
System.out.println("驗證使用者名稱密碼的合法性");
}
}
5.3 關注點重組
實際上編織的過程,是由Spring AOP框架來實現,我們只需要告訴Spring AOP框架,Spring AOP框架自動為我們做這些工作,而不用我們自己編寫程式碼實現。我只需要在配置檔案(.xml)中做配置即可。配置檔案程式碼如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<!--
1、引入AOP的名稱空間
2、目標類
3、切面
4、攔截器 由spring內部實現
5、aop的配置
-->
<bean id="transaction" class="cn.miao.login.aop.cglib.Transaction"></bean>
<bean id="login" class="cn.miao.login.aop.cglib.Login"></bean>
<!--
aop的配置
-->
<aop:config>
<!--
切入點表示式
expression
確定哪個類可以生成代理物件
id 唯一標識
-->
<aop:pointcut expression="execution(* cn.miao.login.aop.cglib.Login.*(..))" id="perform"/>
<!--
切面
-->
<aop:aspect ref="transaction">
<!--
前置通知
* 在目標方法執行之前
*
-->
<aop:before method="beginTransaction" pointcut-ref="perform"/>
<aop:after method="commit" pointcut-ref="perform"/>
</aop:aspect>
</aop:config>
</beans>
5.4 測試
測試程式碼:
@Test
public void testLogin() {
ApplicationContext context = new ClassPathXmlApplicationContext("cn/miao/login/aop/cglib/applicationContext.xml");
Login login = (Login) context.getBean("login");
login.login();
}
執行結果:
開啟事務
驗證使用者名稱密碼的合法性
提交事務
5.5 需求變更
當然我們假設出現和4.4 OOP實現相同的變更,這時我們需要加入日誌功能。這時我們只需要增加Logger類同OOP實現。並在配置檔案中增加如下資訊:
<bean id="logger" class="cn.miao.login.aop.cglib.change.Logger"></bean>
<aop:aspect ref="logger">
<!--
前置通知
* 在目標方法執行之前
*
-->
<aop:after method="logging" pointcut-ref="perform"/>
</aop:aspect>
是不是很方便,只需要擴張,而無需對程式碼進行變更。這就是AOP在處理類似切面上優勢。
6 AspectJ實現
實現
Login類同4.4 Spring AOP實現。
事務處理類Transaction是一個切面如下:
public aspect Transaction {
//切入點
pointcut beginTransaction() : execution(* cn.miao.login.aop.aspectj.Login.login(..));
//前置通知
before() : beginTransaction() {
System.out.println("開啟事務");
}
pointcut commit() : execution(* cn.miao.login.aop.aspectj.Login.login(..));
//後置通知
after() : commit() {
System.out.println("提交事務");
}
}
測試
/**
* 在執行前需要先用ajc命令編譯
*/
public class Client{
public static void main(String []args) {
Login login = new Login();
login.login();
}
}
執行結果:
開啟事務
驗證使用者名稱密碼的合法性
提交事務
需求變更
增加切面Logger。
public aspect Logger {
pointcut logging() : execution(* cn.miao.login.aop.aspectj.change.Login.login(..));
after() returning() : logging() {
System.out.println("logging");
}
}
測試客戶端不需要做任何變動,在執行前需要重新編譯。執行結果如下:
開啟事務
驗證使用者名稱密碼的合法性
logging
提交事務
7,AOP與OOP的區別
AOP在00P的基礎上提出了切面(Aspect)的概念。它與00P的區別首先表現在AOP引入了人們認識系統的一個全新的視角:方面。一個系統按照00P的視角可以按照功能“縱向”分割為一個個的物件。而AOP則從“橫向”的角度將系統的一部分分割為一個個方面。
其次,在AOP裡,每個物件並不知道自己是否被其他關注點 (方面)關注(橫切),也不知道有多少關注點正在關注自己。所有這些資訊都在方面裡定義。而00P則相反,每個物件都知道自己是否需要新增關注點,需要新增多少關注點。也就是說,在AOP裡,組合的流向是從橫切關注點到一般關注點(物件本身)。而00P則相反。這是AOP和00P的主要區別。
第三,在00P裡每個物件的功能在編譯期或者在程式碼編寫階段就決定了。而在AOP中.方面的功能需要在執行“織入”之後才新增到物件之中。因此一個物件的功能最終確定的時間取決於方面織入的時間,可能在編譯期,也可能在裝載期或者執行期[16]。
雖然AOP在OOP之後提出,並且志在更好得解決00P所面臨的問題。但是AOP與00P並不是相互競爭的兩種技術。人們不是為了代替00P而提出AOP。事實上AOP與00P兩者互相之間是一個很好的補充。AOP補充了00P的不足。事實上AOP也能
夠補足其他的程式設計範型。像面向過程的程式設計。但是因為00P是現在的主流範型。所以大部分AOP工具都是對00工具的擴充套件。人們也更熱衷於AOP對00P的補充[16]8 AOP的優點
8.1 程式碼可讀性
程式碼集中易於理解 解決了由於OOP 跨模組造成的程式碼混亂和程式碼分散。OOP同時實現幾個關注點模糊了不同關注點的實現,使得關注點與其實現之間的對應關係不明顯。軟體系統中的模組可能要同時兼顧幾個方面的需要。舉例來說:開發者經常要同時考慮業務邏輯,效能,同步,日誌和安全問題,兼顧各方面的需要導致相應關注點的實現元素同時出現,引起程式碼混亂,AOP可以把這種需求作為獨立的方面很容易的實現,可讀性好。在上面的應用例子中,我們很容易發現OOP實現中,業務方法login()方法不僅有業務邏輯-登入,而且混雜了很多事務處理和日誌記錄等功能程式碼。當這種橫切功能很多時,程式碼就比較混亂了。而在AOP實現(包括Spring AOP實現和AspectJ實現中)login方法中只有登入的業務邏輯,事務處理和日誌記錄等橫切功能都分散在相應的切面中,業務邏輯很清晰,程式碼可讀性自然很好。
8.2 程式碼冗餘度
在OOP中,由於橫切關注點本來就涉及多個模組,其相關實現也就得遍佈在這些模組裡,如在一個使用了資料庫的系統裡,效能問題就會影響所有資料庫的模組,這導致程式碼分散在各處。而AOP模組化橫切關注點,用最小的耦合處理每個關注點,使得即使是橫切關注點也是模組化的。這樣的實現產生的系統,其程式碼的冗餘小。模組化的實現還得系統容易理解和維護。在AOP實現中橫切面的程式碼都是公用的,橫切功能的程式碼只需要寫一次。而在OOP實現中,如果出現新的也業務邏輯,在新的業務邏輯中又存在橫切功能(如日誌等),則這些橫切程式碼又要重複的寫一遍。所以AOP實現比OOP實現程式碼冗餘度低很多。
8.3 程式碼擴充套件性
系統容易擴充套件 由於方面模組根本不知道橫切關注點所以很容易通過建立新的方面加入新的功能,另外,當往系統中加入新的模組時,已有的方面自動橫切進來使系統易於擴充套件,設計師可以推遲為將來的需求作決定,因為他可以把這種需求作為獨立的方面很容易地實現。在上面的應用示例中,我們可以清楚的看到在需求變更的情況下,AOP表現出很好的程式碼擴充套件性,只需要增加新的切面,或者修改配置檔案,而不用行OOP實現,要修改業務邏輯程式碼。AOP很好的符合對擴充套件開放,對修改關閉的原則。
8.4 程式碼重用率
更好的程式碼重用性,AOP把每個切面實現為獨立的模組,模組之間是鬆散耦合的。舉例來說,上文中應用的例子中,Logger和Transaction切面都是作為獨立的模組存在的,它們之間幾乎不存在耦合,鬆散耦合的實現通常意味著更好的程式碼重用性AOP 在使系統實現鬆散耦合這一點上比OOP做得更好 [2,16] 。
9 結論
AOP是在OOP的基礎上提出來的,為軟體系統中橫切功能提供非常好的實現方案,彌補了OOP在解決橫切問題中不足。深入討論了AOP的基本概念,包括Advice, Pointcut等。研究了常用AOP編織時機,一個是AspectJ的靜態編織,也就是編譯時織入,優點是程式碼執行的效率更高,缺點是每次修改程式碼後要重新編譯程式碼;另一個是Spring AOP的動態編織,也就是程式碼執行時編織,優點是修改程式碼後不需要使用專門的編譯工具重新編譯即可部署,缺點是程式碼優化度不高,執行效率稍微差些。
AOP語言的實現中主要研究SpringAOP的實現,第一個核心的模組是AopProxy代理物件的生成,使用的是jdk動態代理或者cglib動態技術來實現的。第二個核心模組是Spring AOP攔截器的呼叫,其實也就是實現了通知的呼叫。
AOP應用中通過一個簡單的登入的業務邏輯,採用OOP實現,AOP實現(Spring AOP實現和AspectJ實現)三種實現方式,並且觀察了三種實現方式在應對需求變更情況下的反應,發現了AOP技術與OOP技術相比在處理橫切邏輯時,具有程式碼可讀性好,冗餘度低,擴充套件性好,重用率高這四個優點。
總之AOP技術以及隨之而來的各種AOP語言出現,給我們軟體系統的開發帶來了更多思想武器和開發工具,如果善以研究和利用將為我們軟體開發帶來很多驚喜。
目前AOP技術應用和研究系列博文規劃為六篇,目前已經完成,目錄見下文。其中AOP技術應用和研究應用示例程式碼已經完成,我已經分享在了github上有任何錯誤或者疑問歡迎聯絡[email protected]。具體參考文獻,參見文末,如果有未加註明的,請聯絡,我將及時修改或刪除。
相關推薦
AOP技術應用和研究--AOP簡單應用
為了更好的理解AOP實踐和體現AOP的優勢,我們始終將OOP和AOP的比較貫穿到下文中。並在最終總結出AOP與OOP相比所擁有的優點,AOP的缺點以及AOP一般的使用場景。 1.1 問題空間到解空間的對映 在比較研究OOP和AOP實踐之前,先讓解決從
邏輯回歸和梯度下降簡單應用案例
error () body xlabel 所有 def app 4.6 9.4 實例: 我們將建立一個邏輯回歸模型來預測一個學生是否被大學錄取。 假設你是一個大學系的管理員,你想根據兩次考試的結果來決定每個申請人的錄取機會。 你有以前的申請人的歷史數據,你可以用它作為邏輯回
NFS和SAMBA的簡單應用(一)
NFS和SAMBA的簡單應用NFS和SAMBA的簡單應用(一) (1)使用samba和NFS分別共享/data目錄; (2)讓samba客戶端和NFS客戶端分別掛載samba服務器上共享的/data/至本地的/mydata目錄;本地的mysqld或mariadb服務的數據目錄設置為/myda
自動化測試(一)-get和post的簡單應用
今天主要介紹兩種測試的介面post和get: get和post是http的兩種基本請求方式,區別在於get把引數包含在url中傳遞;給而post把引數以json或鍵值對的方式利用工具傳遞。 get的傳遞隨便找個遊覽器就可以進行介面測試: 舉個栗子:這是個獲取學生資訊的介面 介面資訊:1:url
c++的STL中棧和佇列的簡單應用
1.棧和佇列所在標頭檔案 佇列所在C++標頭檔案<queue> 棧所在C++標頭檔案<stack> 2.定義實現 queue<int> q; stack<int> s; 3.佇列中的常見函式 q.empty(); bool型
棧和佇列的簡單應用
1:編寫一個演算法來判別表示式中的括號是否匹配,以字元"\0"作為算術表示式的結束符。(圓括號,花括號,中括號三種類型) 基本思想: 1)掃描每個字元,遇到花、中、圓的左括號進棧 2)遇到花、中、圓的右括號時檢查棧頂元素是否為對應的左括號。若是,退棧,否則配對錯誤。 3)最後棧不為空
系統技術非業餘研究 » ioprofile調查應用IO情況的利器
我們在做IO密集型的應用程式的時候,比如MySQL資料庫,通常系統的表現取決於workload的型別。 比如我們要調優,我們就必須非常清楚的知道資料的訪問規律,收集到足夠的資料,用來做調優的依據。 有很多工具可以收集系統層面的,裝置層面的,程序層面的IO資料,但是沒有一個現成的工具可以回答我們比如
Ajax實現區域性重新整理和非同步處理簡單應用(實現簡單註冊驗證)
4.//從資料庫中查詢相應欄位並反饋給servlet 部分 @SuppressWarnings({ "unused", "null" }) public User find(String name){ List<Map<String,Object>> lists=new Arra
登入時記住密碼——Filter、Cookie和Session的簡單應用
思路:當用戶進入某一頁面時,用過濾器進行預處理,判斷Session中是否有儲存使用者的登入資訊,如果沒有,則從Cookie中查詢是否有儲存使用者登入資訊的cookie,如果有將其取出,進行登入操作。 1. 使用者的登入頁面login.jsp: <%@ page la
Http的get和post請求簡單應用
網路請求中需要遵循http協議,而http有許多方法,大家一般最常用的就是post和get請求方法了! 其中,post和get都可以向伺服器傳送和請求資料,而我們一般都習慣用get請求資料,post傳送資料!get方法是把資料拼接到請求行裡面,我們可以直接看到
教你如何繪制數學函數圖像——numpy和matplotlib的簡單應用
科學計算 安裝 tran ctrl 命令行 bsp 數學函數 包含 數值計算 numpy和matplotlib的簡單應用 一、numpy庫 1.什麽是numpy NumPy系統是Python的一種開源的數值計算擴展。這種工具可用來存儲和處理大型矩陣,比Python自身
12-factor應用和微服務架構應用的區別
gem 很多 image RR all ans 幫助文檔 john http SAP雲平臺的幫助文檔很多時候將12-factor應用和微服務架構的應用相提並論。 然而從Allan Beck和John Mcteague的Cloud成熟度模型概念裏,12-factor應用從成
popup的簡單應用舉例 popup的簡單應用舉例(具體在增刪改查元件中用到)以及補充的知識點
popup的簡單應用舉例(具體在增刪改查元件中用到)以及補充的知識點 一、首先說一下自執行函式 1. 立即執行函式是什麼?也就是匿名函式 立即執行函式就是
系統技術非業餘研究 » slabtop簡單的用途
我們知道核心的模組在分配資源的時候,為了提高效率和資源的利用率,都是透過slab來分配的。我們通過slab的資訊,再配合原始碼能粗粗瞭解系統的執行情況,比如說什麼資源有沒有不正常的多,或者什麼資源有沒有洩漏。 linux系統透過/proc/slabinfo來向用戶暴露slab的使用情況的,我們來看
EMV技術學習和研究(八)終端風險管理
如果交易在上述的過程中被選中,則將TVR中的“交易被隨機選中進行聯機處理”位設為‘1’。 終端風險管理引數示例 引數 值 終端最低限額
EMV技術學習和研究(十三)CDA認證
轉載請註明出處 作者:小旭 之前離線資料認證,包括後面的GAC都忽略了CDA的存在,現在專門討論一下CDA。 先從離線資料認證開始,第一次遇到CDA。 CDA的前面三個步驟(獲取ca公鑰、恢復髮卡行公鑰、恢復IC卡公鑰)和DDA一樣,DDA是通過內部認證指令獲取簽名動態資
EMV技術學習和研究(十)聯機處理 以及 交易結束
轉載請註明出處 作者:小旭 前面終端執行完終端行為分析後,如果在GAC1的時候,卡片返回ARQC,那麼終端就需要進行聯機交易流程的處理,這一部分我們主要討論一下聯機交易的處理過程。 在終端獲取到卡片返回ARQC後,終端先發起8583報文請求,然後接收到後臺返回的報文,提取相
EMV技術學習和研究
今天在工作中碰到一些問題,就找到了這篇文章,個人感覺很好,儲存下來,以供隨時學習。 作者:小旭 目的: 應用選擇主要目的就是在卡片插入終端的時候,由終端來選擇哪些應用是由終端和卡片共同支援的。終端的AID列表是通過AID下載交易從服務端獲取,卡片的AID是在做卡片個
EMV技術學習和研究(十二)交易限額
轉載請註明出處 作者:小旭 EMV引數裡面有幾個限額,但是感覺這幾個限額都比較容易混淆和模糊,下面一個一個的來討論一下。 終端最低限額(9F1B)、終端電子現金交易限額(9F7B)、非解最低限額(DF19)、非解交易限額(DF20)、CVM限額(DF21) 9F1B,就是所
Java的poi技術讀取和匯入Excel簡單例項
專案結構: 用到的Excel檔案: XlsMain .java 類 //該類有main方法,主要負責執行程式,同時該類中也包含了用poi讀取Excel(2003版) import java.io.FileInputStream; import java.io.