spring框架學習之路(一)-入門基礎(2)-動態代理和AOP(面向切面編程)

  spring框架學習之路(一)-入門基礎(1)-IOC(控制反轉)&DI(依賴注入);
  之前寫了關於spring的內核IOC&DI的一些內容,現在接着寫spring的另一個重要概念AOP。
  AOP(Aspect Oriented Programming):面向切面編程。與OOP(面向對象編程)自上而下的程序結構不同的是,AOP是針對於程序切面。
  比如日誌記錄,我們需要對多個類中的多個方法執行前或執行後進行記錄日誌,如果我們對每一個方都添加相同的記錄日誌的代碼,就違反了DRY(Don’t repeat yourself)原則。所以出現了AOP,AOP就是在程序的水平結構上進行整體程序設計,而不需要針對每一個方法進行設計。
  要了解AOP,就必須瞭解“代理模式”(不瞭解的百度吧…設計模式的坑以後填…),而AOP利用的就是“動態代理”。
  簡單來說,AOP主要就是動態生成和不同的“真實角色”相對應的“代理角色”。核心就是InvocationHandler接口 和Proxy.newProxyInstance() 方法。
  老規矩,舉個栗子~~~

//抽象角色
public interface AbsRole {  
    void doActive();
}
//真實角色
public class RealRole implements AbsRole {
    @Override
    public void doActive() {
        System.out.println("active from real role!");
    }
}

  然後創建一個InvocationHandler,InvocationHandler只有一個invoke()方法,而我們只需要在裏面實現method.invoke(obj, args);就可以調用 對象obj的方法method,此方法參數爲args,返回值爲res。
  在這條語句前後加入邏輯,就可以實現每次執行方法method時都會附帶執行前後邏輯。(這裏就是前後的兩條輸出語句)

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

public class ProxyRole implements InvocationHandler {

    private Object obj;

    public ProxyRole(Object obj) {
        super();
        this.obj = obj;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        System.out.println("previous method");
        Object res=method.invoke(obj, args);
        System.out.println("after method");
        return res;
    }   
}

main方法的執行方法爲:

    public static void main(String[] args) {    
        RealRole real=new RealRole();       
        AbsRole abs=(AbsRole) Proxy.newProxyInstance(RealRole.class.getClassLoader(), RealRole.class.getInterfaces(), new ProxyRole(real));
        abs.doActive();
    }

大體邏輯執行過程就是:
  通過Proxy.newProxyInstance()方法生成一個對象,此對象繼承$Proxy0類,並實現真實角色的接口,並且此對象擁有一個InvocationHandler h對象的應用。然後用一個抽象角色abs引用這個對象。
  執行abs.doActive()時,此對象在doActive()方法中的具體實現就是調用h.invoke()方法,這樣在h.invoke()中就實現了對真實角色方法的執行。
  **另外需要注意的是,在ProxyRole類中
  public Object invoke(Object proxy, Method method, Object[] args)
  方法中的proxy對象不是真實角色的應用,而是動態生成的代理角色(就是那個繼承自$Proxy0類的對象)的引用。**

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章