上次的博文深入淺出SPRing(二) IoC詳解中,我為大家簡單介紹了一下Spring框架核心內(nèi)容中的IoC,接下來我們繼續(xù)講解另一個核心AOP(aspect Oriented Programming),即面向切面編程。
在介紹AOP之前先來回顧一下大家都比較熟悉的OOP(Object Oriented Programming)。OOP主要是為了實現(xiàn)編程的重用性、靈活性和擴展性。它的幾個特征分別是繼承、封裝、多態(tài)和抽象。OOP重點體現(xiàn)在編程架構(gòu),強調(diào)的是類之間的層次關(guān)系。
為了更好的說明OOP的概念,我們接下來講一個OOP的實例,重點分析OOP存在哪些缺陷,以便更好的理解AOP的相關(guān)內(nèi)容。
先看如下的一張圖:

上面這張圖有三個類:Dog,Cat和Duck,他們都有一個方法run。按照OOP的設(shè)計理念,我們很容易就會想到抽象出一個Animal父類,同時讓這三個子類繼承Animal父類。這樣的設(shè)計可以用如下的圖示表示:

在OOP思想中,我們會使用大量的類似上圖的編程方式,對類進(jìn)行抽象、繼承、封裝和多態(tài)來實現(xiàn)編程的重用性、靈活性和擴展性。但是這樣的編程仍然有一定的局限性,有時候,OOP并不能很好解決我們再實際開發(fā)中遇到的問題。為了說明這個問題,看下面的圖示:

看到上面的圖,我們暫時還不能發(fā)現(xiàn)有什么問題。為了大家便于理解,接下來我來給大家講解一下上面類圖的實現(xiàn)過程。描述如下:馬戲團(tuán)有一條表演的小狗,這條小狗可以跑和跳,但是它完成跑和跳兩個動作之前必須是在接到馴獸師發(fā)出的命令后,同時完成跑和跳的動作之后,馴獸師會給與響應(yīng)的獎勵,比如一塊肉。
了解了實現(xiàn)過程之后,我們在來看一下具體的代碼。


public class Dog { public void run() { System.out.println("馴獸師發(fā)出命令!") System.out.println("小狗開始跑!"); System.out.pringln("馴獸師給與獎勵"); } public void jump() { System.out.println("馴獸師發(fā)出命令!") System.out.println("小狗開始跳!"); System.out.pringln("馴獸師給與獎勵"); } }

仔細(xì)看上面的代碼,我們可以看出在run方法和jump方法中,存在一些相同的內(nèi)容(馴獸師發(fā)出命令和給與獎勵),這些內(nèi)容并不能完全進(jìn)行抽象,即不能按照OOP編程思想進(jìn)行處理。類似這樣的情況同樣會出現(xiàn)在我們編程中的很多地方,例如:日志記錄、性能統(tǒng)計、安全控制、事務(wù)處理、異常處理等等。但是這樣的情況該如何解決呢?這就引入了AOP編程思想。
3、AOP簡介
AOP為Aspect Oriented Programming的縮寫,即面向切面編程(也叫面向方面),是一種可以通過預(yù)編譯方式和運行期動態(tài)代理實現(xiàn)在不修改源代碼的情況下給程序動態(tài)統(tǒng)一添加功能的一種技術(shù)。
4、AOP實現(xiàn)實例
為了大家更好的理解AOP如何實現(xiàn),接下來我們優(yōu)化一下上述代碼。
首先是Dog類


public interface Animal { public void run(); public void jump(); } public class Dog implements Animal{ public void run(){ System.out.println("小狗開始跑!"); } public void jump(){ System.out.println("小狗開始跳!"); } }

對比之前的代碼我們可以明顯看出,我們將關(guān)于馴獸師的相關(guān)內(nèi)容從run和jump中進(jìn)行了抽取,接下來,我們?nèi)绾卧诔绦蜻\行中將關(guān)于馴獸師的動作加入到程序中呢?這就是我們這次用到的AOP實現(xiàn)的核心技術(shù)動態(tài)代理(Dynamic Proxy)。具體代碼如下:


public class MyProxy implements InvocationHandler{ private Object targetObject; public Object createProxyInstance(Object targetObject) { this.targetObject = targetObject; return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), targetObject.getClass().getInterfaces(), this); } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { command(); Object ret = method.invoke(targetObject, args); award(); return ret; } private void command() { System.out.println("馴獸師發(fā)出命令!"); } private void award(){ System.out.println("馴獸師給與獎勵!"); } }

上述代碼實現(xiàn)完成之后,我們改如何調(diào)用呢?參考代碼如下:

public class Client { public static void main(String[] args) { MyProxy hander = new MyProxy(); Animal dog = (Animal)hander.createProxyInstance(new Dog()); dog.run(); dog.jump(); } }

執(zhí)行結(jié)果如下:
關(guān)于AOP編程的實例演示就完成了,接下來重新回顧一下AOP與OOP的相關(guān)概念。
5、AOP與OOP的關(guān)系
OOP針對業(yè)務(wù)處理過程的實體(Dog、Cat、Duck)及其屬性和行為(run)進(jìn)行抽象封裝,以獲得更加清晰高效的邏輯單元劃分。而AOP則是針對業(yè)務(wù)處理過程中(run或jump)的切面(command和award)進(jìn)行提取,它所面對的是處理過程中的某個步驟或階段,以獲得邏輯過程中各部分之間低耦合性的隔離效果。這兩種設(shè)計思想在目標(biāo)上有著本質(zhì)的差異。 本篇文章到此為止基本上對AOP的概念就講解完畢了,至于在Spring中如何使用AOP,我會在今后的博文中針對一個實例進(jìn)行講解,另外本次關(guān)于AOP我們并沒有講完,還有很多的概念同樣我會在以后的博文中進(jìn)行講解!敬請期待!
新聞熱點
疑難解答