Spring理論基礎-面向切面編程

AOPAspect-Oriented Programming的縮寫,中文翻譯是面向切面編程。做爲Spring的特徵之一,是要好好學習的。git

首先面向切面編程這個名稱很容易讓人想起面向對象編程(OOP)來。咱們知道面向對象編程是從上往下的把系統拆分紅若干個類,如Web項目中常見的ControllerServiceDao等分層。可是面向對象編程對於從左到右的水平抽象十分無力,相似於日誌、權限等系統級功能的代碼會重複的出如今任何地方。簡單的說,面向切面編程是對面向對象編程的一種補充,它能夠把系統裏一些分散的重複代碼集中在一塊兒,抽象成一個切面。先來舉一個例子:github

有一個內部使用的管理系統,Controller中的每一個接口在調用時都要記錄下當前用戶名稱、當前時間等參數。編程

很明顯這個需求的實現代碼在每一個接口中都是重複的。即便提取成公共類的公共方法,在每一個接口裏也都有一句該公共方法的調用,致使類之間的耦合。bash

接口流程圖

咱們但願把原來接口中的記錄代碼去除掉,使這些接口只關注本身的業務邏輯。而後使用預編譯或運行期動態代理等方式實如今不修改接口代碼的狀況下,爲接口添加記錄功能。這種動態地將代碼織入到類的指定方法、指定位置上的編程思想就是面向切面編程。markdown

接口流程圖(添加AOP)

概念

面向切面編程具體的一些概念。ide

《EXPERT ONE ON ONE J2EE DEVELOPMENT WITHOUT EJB》第8章、《Spring實戰》第4章:oop

  • 加強(advice,另譯爲通知,但《Spring3.x企業應用開發實戰》做者不同意):在特定鏈接點執行的動做。例子中的實現代碼就是加強。學習

  • 切點(pointcut):一組鏈接點的總稱,用於指定某個加強應該在什麼時候被調用。例子中的指定哪些接口和指定位置就是切點。ui

  • 鏈接點(join point):在應用執行過程當中可以插入切面的一個點。例子中具體的一個接口和指定位置的結合就是鏈接點。this

  • 切面(aspect):通知(即加強)和切點的結合。

AOPSpring中主要是經過動態代理實現的,具體實現也分爲兩種:JDK動態代理CGLIB動態代理。其中JDK動態代理是基於接口代理,CGLIB動態代理是基於繼承代理。

JDK動態代理

做爲Java自帶的一種動態代理技術,JDK動態代理的優點是使用反射技術來生成代理類,在生成效率上比較高。缺點是隻能基於接口來動態代理,若是目標類沒有實現任何接口是不能使用JDK動態代理的。

來看一個用JDK動態代理的例子。

public class DynamicProxy implements InvocationHandler {

    /**
     * 被代理類
     */
    private Object target;

    public DynamicProxy(Object target) {
        this.target = target;
    }

    public static Object bind(Object target) {
        InvocationHandler invocationHandler = new DynamicProxy(target);
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), invocationHandler);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println(method.getName() + " 方法執行前");
        //執行被代理類方法
        Object ret = method.invoke(target, args);
        System.out.println(method.getName() + " 方法執行後");
        return ret;
    }

    public static void main(String[] args) {
        Dao dao = new OrderDao();
        dao.doSomeThing();
        Dao daoProxy = (Dao) DynamicProxy.bind(dao);
        daoProxy.doSomeThing();
    }

}
複製代碼
public class OrderDao implements Dao {

    @Override
    public void doSomeThing() {
        System.out.println("test");
    }

}
複製代碼
public interface Dao {

    void doSomeThing();

}
複製代碼
輸出:
test
doSomeThing 方法執行前
test
doSomeThing 方法執行後

Process finished with exit code 0
複製代碼

後記

此次只是梳理下概念,把本身理解的AOP概念寫下來。也參考了不少文章,大致都是一致的細節上有些不一樣,把本身理解的寫出來給你們看下就知道有沒有錯了。順便整理一下,省得之後別人問起本身支支吾吾的不知道從哪提及。並無去了解Spring中具體的AOP實現,有興趣的同窗能夠自行深刻了解下。

個人博客地址

參考資料

什麼是面向切面編程AOP?

好書一塊兒讀(115):重學Spring之面向切面

相關文章
相關標籤/搜索