欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
AOP實(shí)現原理:從命令式編程和聲明式編程說(shuō)起 - 51CTO.COM

面向方面編程(Aspect Oriented Programming,簡(jiǎn)稱(chēng)AOP)是一種聲明式編程(Declarative Programming)。聲明式編程是和命令式編程(Imperative Programming)相對的概念。我們平時(shí)使用的編程語(yǔ)言,比如C++、Java、Ruby、Python等,都屬命令式編程。命令式編程的意思是,程序員需要一步步寫(xiě)清楚程序需要如何做什么(How to do What)。聲明式編程的意思是,程序員不需要一步步告訴程序如何做,只需要告訴程序在哪些地方做什么(Where to do What)。比起命令式編程來(lái),聲明式編程是在一個(gè)更高的層次上編程。聲明式編程語(yǔ)言是更高級的語(yǔ)言。聲明式編程通常處理一些總結性、總覽性的工作,不適合做順序相關(guān)的細節相關(guān)的底層工作。

如果說(shuō)命令式編程是拼殺在第一線(xiàn)的基層工作人員,聲明式編程就是總設計師、規則制定者。聲明式編程語(yǔ)言的概念,和領(lǐng)域專(zhuān)用語(yǔ)言(Domain Specific Language,簡(jiǎn)稱(chēng)DSL)的概念有相通之處。DSL主要是指一些對應專(zhuān)門(mén)領(lǐng)域的高層編程語(yǔ)言,和通用編程語(yǔ)言的概念相對。DSL對應的專(zhuān)門(mén)領(lǐng)域(Domain)一般比較狹窄,或者對應于某個(gè)行業(yè),或者對應于某一類(lèi)具體應用程序,比如數據庫等。

最常見(jiàn)的DSL就是關(guān)系數據庫的結構化數據查詢(xún)語(yǔ)言SQL。同時(shí),SQL也是一門(mén)聲明式語(yǔ)言。SQL只需要告訴數據庫,處理符合一定條件的數據,而不需要自己一步步判斷每一條數據是否符合條件。SQL的形式一般是 select … where …,update … where …,delete … where …。當然,這樣一來(lái),很多基層工作,SQL做不了。因此,大部分數據庫都提供了另外的命令式編程語(yǔ)言,用來(lái)編寫(xiě)存儲過(guò)程等,以便處理一些更加細節的工作。

常見(jiàn)的DSL還有規則引擎(Rule Engine)語(yǔ)言、工作流(Workflow)語(yǔ)言等。規則引擎和工作流同時(shí)帶有命令式編程和聲明式編程的特點(diǎn)。規則引擎允許用戶(hù)按照優(yōu)先級定義一系列條件組合,并定義對滿(mǎn)足條件的數據的處理過(guò)程。工作流也大致類(lèi)似。工作流把最基本的條件判斷和循環(huán)語(yǔ)句的常見(jiàn)組合,定義為更加高級復雜的常用程序流程邏輯塊。用戶(hù)可以用這些高級流程塊組合更加復雜的流程塊,從而定義更加復雜的流程跳轉條件。用戶(hù)也可以定義當程序運行上下文滿(mǎn)足一定條件的時(shí)候,應該做什么樣的處理工作。規則引擎和工作流的語(yǔ)言形式有可能是XML格式,也有可能是Ruby、Python、Javascript等腳本格式。我個(gè)人比較傾向于腳本格式,因為XML適合表達結構化數據,而不擅長(cháng)表達邏輯流程。當然,XML格式的好處也是顯而易見(jiàn)的。解析器可以很容易分析XML文件的結構,XML定義的條件或者程序流程都可以很方便地作為數據來(lái)處理。

介紹了聲明式編程和DSL之后,我們來(lái)看本章題目表達的內容——AOP。AOP是聲明式編程,AOP語(yǔ)言也可以看作是DSL。AOP語(yǔ)言對應的專(zhuān)門(mén)領(lǐng)域(Domain)就是程序結構的方方面面(Aspect),比如程序的類(lèi)、方法、成員變量等結構,以及針對這些程序結構的通用工作處理,比如日志管理、權限管理、事務(wù)管理等。

AOP處理的工作內容一般都是這樣的一些總結性工作:“我想讓所有的數據庫類(lèi)都自動(dòng)進(jìn)行數據庫映射”、“我想打印出所有業(yè)務(wù)類(lèi)的工作流程日志”、“我想給所有關(guān)鍵業(yè)務(wù)方法都加上事務(wù)管理功能”、“我想給所有敏感數據處理方法都加上安全管理授權機制”等等。
下面我們介紹AOP的實(shí)現原理和使用方法。

AOP實(shí)現原理

AOP的實(shí)現原理可以看作是Proxy/Decorator設計模式的泛化。我們先來(lái)看Proxy模式的簡(jiǎn)單例子。

  1. Proxy {  
  2.     innerObject; // 真正的對象  
  3.     f1() {  
  4.         // 做一些額外的事情  
  5.  
  6.         innerObject.f1(); // 調用真正的對象的對應方法  
  7.  
  8.           // 做一些額外的事情  
  9.     }  
  10. }  

在Python、Ruby等動(dòng)態(tài)類(lèi)型語(yǔ)言中,只要實(shí)現了f1()方法的類(lèi),都可以被Proxy包裝。在Java等靜態(tài)類(lèi)型語(yǔ)言中,則要求Proxy和被包裝對象實(shí)現相同的接口。動(dòng)態(tài)語(yǔ)言實(shí)現Proxy模式要比靜態(tài)語(yǔ)言容易得多,動(dòng)態(tài)語(yǔ)言實(shí)現AOP也要比靜態(tài)語(yǔ)言容易得多。假設我們用Proxy包裝了10個(gè)類(lèi),我們通過(guò)調用Proxy的f1()方法來(lái)調用這10個(gè)類(lèi)的f1()方法,這樣,所有的f1()調用都會(huì )執行同樣的一段“額外的工作”,從而實(shí)現了“所有被Proxy包裝的類(lèi),都執行一段同樣的額外工作”的任務(wù)。這段“額外的工作”可能是進(jìn)行日志記錄,權限檢查,事務(wù)管理等常見(jiàn)工作。

Proxy模式是可以疊加的。我們可以定義多種完成特定方面任務(wù)(Aspect),比如,我們可以定義LogProxy、SecurityProxy、TransactionProxy,分別進(jìn)行日志管理、權限管理、事務(wù)管理。

  1. LogProxy {  
  2.       f1(){  
  3.             // 記錄方法進(jìn)入信息  
  4.  
  5.             innerObject.f1();// 調用真正的對象的對應方法  
  6.  
  7.           // 記錄方法退出信息  
  8.     }  
  9. }  
  10.  
  11. SecurityProxy {  
  12.       f1(){  
  13.           // 進(jìn)行權限驗證  
  14.  
  15.           innerObject.f1();// 調用真正的對象的對應方法  
  16.       }  
  17. }  
  18.  
  19. TransactonProxy {  
  20.       f1(){  
  21.           Open Transaction  
  22.  
  23.           innerObject.f1();// 調用真正的對象的對應方法  
  24.  
  25.           Close Transaction  
  26.       }  
  27. }  

根據AOP的慣用叫法,上述的這些Proxy也叫做Advice。這些Proxy(or Advice)可以按照一定的內外順序套起來(lái),最外面的Proxy會(huì )最先執行。包裝f1()方法,也叫做截獲(Intercept)f1()方法。Proxy/Advice有時(shí)候也叫做Interceptor。

看到這里,讀者可能會(huì )產(chǎn)生兩個(gè)問(wèn)題。

問(wèn)題一:上述代碼采用的Proxy模式只是面向對象的特性,怎么會(huì )扯上一個(gè)新概念“面向方面(AOP)”呢?

問(wèn)題二:Proxy模式雖然避免了重復“額外工作”代碼的問(wèn)題,但是,每個(gè)相關(guān)類(lèi)都要被Proxy包裝,這個(gè)工作也是很煩人。AOP Proxy如何能在應用程序中大規模使用呢?

下面我們來(lái)解答著(zhù)兩個(gè)問(wèn)題。

對于問(wèn)題一,我們來(lái)看一個(gè)復雜一點(diǎn)的例子。假設被包裝對象有f1()和f2()兩個(gè)方法都要被包裝。

  1. RealObject{  
  2.       f1() {…}  
  3.       f2() {…}  

這個(gè)時(shí)候,我們應該如何做?難道讓Proxy也定義f1()和f2()兩個(gè)方法?就象下面代碼這樣?

  1. Proxy {  
  2.     innerObject; // 真正的對象  
  3.     f1() {  
  4.         // 做一些額外的事情  
  5.  
  6.         innerObject.f1(); // 調用真正的對象的對應方法  
  7.  
  8.         // 做一些額外的事情  
  9.     }  
  10.  
  11.     f2() {  
  12.         // 做一些額外的事情  
  13.          
  14.         innerObject.f2(); // 調用真正的對象的對應方法  
  15.          
  16.         // 做一些額外的事情  
  17.     }  
  18.  
  19. }  

這樣做有幾個(gè)不利之處。一是會(huì )造成代碼重復,Proxy的f1()和f2()里面的“做一些額外的事情”代碼重復。二是難以擴展,被包裝對象可能有多個(gè)不同的方法,不同的被包裝對象需要被包裝的方法也可能不同?,F在的問(wèn)題就變成,“Proxy如何才能包裝截獲任何類(lèi)的任何方法?”
答案呼之欲出。對,就是Reflection。Java、Python、Ruby都支持Reflection,都支持Method(方法)對象。那么我們就利用Method Reflection編寫(xiě)一個(gè)能夠解惑任何類(lèi)的任何方法的Proxy/Advice/Interceptor。

  1. MethodInterceptor{  
  2.  
  3.     around( method ){  
  4.         // 做些額外的工作  
  5.          
  6.         method.invoke(…); // 調用真正的對象方法  
  7.          
  8.         // 做些額外的工作  
  9.     }  
  10. }  

上述的MethodInterceptor就可以分別包裝和截獲f1()和f2()兩個(gè)方法。

這里的method參數就是方法對象,在Java、Ruby等面向對象語(yǔ)言中,需要用Reflection獲取方法對象。這個(gè)方法對象就相當于函數式編程的函數對象。在函數式編程中,函數對象屬于“一等公民”,函數對象的獲取不需要經(jīng)過(guò)Reflection機制。所以,函數式編程對AOP的支持,比面向對象編程更好。由此我們看到,AOP對應的問(wèn)題領(lǐng)域確實(shí)超出了OOP的力所能及的范圍。OOP只能處理同一個(gè)類(lèi)體系內的同一個(gè)方法簽名的截獲和包裝工作,一旦涉及到一個(gè)類(lèi)的多個(gè)不同方法,或者多個(gè)不同類(lèi)體系的不同方法,OOP就黔驢技窮,無(wú)能為力了。

使用Method Reflection的方式截獲任何方法對象,是AOP的常用實(shí)現手段之一。另一個(gè)常見(jiàn)手段就是自動(dòng)代碼生成了。這也回答了前面提出的問(wèn)題二——如何在應用系統中大規模使用AOP。

Proxy Pattern + Method Reflection + 自動(dòng)代碼生成這樣一個(gè)三元組合,就是AOP的基本實(shí)現原理。Proxy Pattern 和 Method Reflection,前面已經(jīng)做了闡述,下面我們來(lái)講解自動(dòng)代碼生成。

首先,AOP需要定義一種Aspect描述的DSL。Aspect DSL主要用來(lái)描述這樣的內容:“用TransactionProxy包裝截獲business目錄下的所有類(lèi)的公共業(yè)務(wù)方法”、“ 用SecurityProxy包裝截獲所有Login/Logout開(kāi)頭的類(lèi)的所有公共方法”、“用LogProxy包裝截獲所有文件的所有方法”等等。Aspect DSL的形式有多種多樣。有的是一種類(lèi)似Java的語(yǔ)法,比如AspectJ;有的是XML格式或者各種腳本語(yǔ)言,比如,Spring AOP等。

有了Aspect DSL,AOP處理程序就可以生成代碼了。AOP生成代碼有三種可能方式:

(1)靜態(tài)編譯時(shí)期,源代碼生成。為每個(gè)符合條件的類(lèi)方法產(chǎn)生對應的Proxy對象。AspectJ以前就是這種方式。

(2)靜態(tài)編譯時(shí)期,處理編譯后的字節碼。Java、Python之類(lèi)的虛擬機語(yǔ)言都有一種中間代碼(Java的中間代碼叫做字節碼),AOP處理程序可以分析字節碼,并直接產(chǎn)生字節碼形式的Proxy。這種方式也叫做靜態(tài)字節碼增強。AspectJ也支持這種方式。Java有一些開(kāi)源項目,比如 ASM、Cglib等,可以分析并生成Java字節碼。這些開(kāi)源項目不僅可以靜態(tài)分析增強字節碼,還可以在程序運行期動(dòng)態(tài)分析增強字節碼。很多AOP項目,比如Spring AOP,都采用ASM/Cglib處理字節碼。

(3)動(dòng)態(tài)運行時(shí)期,即時(shí)處理裝載到虛擬機內部的類(lèi)結構字節碼。這也叫做動(dòng)態(tài)增強。比如,Spring AOP。如前所述,Spring AOP使用ASM/Cglib之類(lèi)的處理字節碼的開(kāi)源項目。Java運行庫本身也提供了類(lèi)似于A(yíng)SM/Cglib的簡(jiǎn)單的動(dòng)態(tài)處理字節碼的API,叫做 Dynamic Proxy。

以上就是AOP的實(shí)現原理:Proxy Pattern + Method Reflection + Aspect DSL + 自動(dòng)代碼生成。

總體來(lái)說(shuō),實(shí)現AOP的便利程度,函數式編程語(yǔ)言 > 動(dòng)態(tài)類(lèi)型語(yǔ)言 > 靜態(tài)類(lèi)型語(yǔ)言。當然,這個(gè)不等式并不是絕對的。有些動(dòng)態(tài)類(lèi)型語(yǔ)言提供了豐富強大的語(yǔ)法特性,實(shí)現AOP的便利程度,可能要超過(guò)函數式編程語(yǔ)言。

本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
C#之父Anders Hejlsberg演講解讀:編程語(yǔ)言大趨勢
Spring框架與AOP思想的研究與應用
Spring框架中的AOP思想動(dòng)態(tài)代理模式
用費曼技巧自學(xué)編程,香不香?
《Spring設計思想》AOP設計思想與原理(圖文并茂)
由DSL來(lái)了解Groovy的語(yǔ)言特征
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久