面試准備--Spring(AOP)


AOP:面向切面編程,在執行某個指令時,需要添加某個預編譯的指令。

下面這個例子是來自網上的:

1、OOP回顧

       在介紹AOP之前先來回顧一下大家都比較熟悉的OOP(Object Oriented Programming)。OOP主要是為了實現編程的重用性、靈活性和擴展性。它的幾個特征分別是繼承、封裝、多態和抽象。OOP重點體現在編程架構,強調的是類之間的層次關系。

2、OOP缺陷

       為了更好的說明OOP的概念,我們接下來講一個OOP的實例,重點分析OOP存在哪些缺陷,以便更好的理解AOP的相關內容。

       先看如下的一張圖:



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


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



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

       了解了實現過程之后,我們在來看一下具體的代碼。 

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

 

 

       仔細看上面的代碼,我們可以看出在run方法和jump方法中,存在一些相同的內容(馴獸師發出命令和給與獎勵),這些內容並不能完全進行抽象,即不能按照OOP編程思想進行處理。類似這樣的情況同樣會出現在我們編程中的很多地方,例如:日志記錄、性能統計、安全控制、事務處理、異常處理等等。但是這樣的情況該如何解決呢?這就引入了AOP編程思想。

 

3、AOP簡介

       AOP為Aspect Oriented Programming的縮寫,即面向切面編程(也叫面向方面),是一種可以通過預編譯方式和運行期動態代理實現在不修改源代碼的情況下給程序動態統一添加功能的一種技術。

 

4、AOP實現實例

      為了大家更好的理解AOP如何實現,接下來我們優化一下上述代碼。

      首先是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("小狗開始跳!");
        }        
    }

 

      對比之前的代碼我們可以明顯看出,我們將關於馴獸師的相關內容從run和jump中進行了抽取,接下來,我們如何在程序運行中將關於馴獸師的動作加入到程序中呢?這就是我們這次用到的AOP實現的核心技術動態代理(Dynamic Proxy)。具體代碼如下: 

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class MyProxy  implements InvocationHandler{

    private Object targetObject;
    
    /** 
     * 綁定委托對象並返回一個代理類 
     * @param target 
     * @return 
     */  
    public Object createProxyInstance(Object targetObject) {
        this.targetObject = targetObject;        
        return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), 
                               targetObject.getClass().getInterfaces(), 
                               this);
    }
    
    /**
     * @param proxy:指被代理的對象。
     * @param method:要調用的方法
     * @param args:方法調用時所需要的參數 
     */    
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        //注入需要調用的方法
        command();        
        //執行被代理對象的方法,如果方法有返回值則賦值給ret
        Object ret = method.invoke(targetObject, args);
        //注入需要調用的方法
        award();
        return ret;
    }
    
    
    private void command() {
        System.out.println("馴獸師發出命令!");
    }
    private void award(){
        System.out.println("馴獸師給與獎勵!");
    }
}

 


  上述代碼實現完成之后,我們改如何調用呢?參考代碼如下:
 

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

 

         執行結果如下:



       關於AOP編程的實例演示就完成了,接下來重新回顧一下AOP與OOP的相關概念。

 

5、AOP與OOP的關系

       OOP針對業務處理過程的實體(Dog、Cat、Duck)及其屬性和行為(run)進行抽象封裝,以獲得更加清晰高效的邏輯單元划分。而AOP則是針對業務處理過程中(run或jump)的切面(command和award)進行提取,它所面對的是處理過程中的某個步驟或階段,以獲得邏輯過程中各部分之間低耦合性的隔離效果。這兩種設計思想在目標上有着本質的差異。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM