Web項目中靜態代理和動態代理爲基礎的面向切面編程AOP

本來每天更新的,我一般喜歡夜裏過了十二點的時候發文章,結果難道是愚人節嗎?學校的網也很有意思,斷了,把我給耍了。。。好吧…開始今天的話題AOP。AOP太重要了,所以放到第二篇文章來談這個話題,AOP是Spring中的重要概念。如果這個不理解Web開發中的三大框架的原理,那就呵呵了。時常聽到同學和網友議論Web程序員大部分時間都是在考皮XML配置,我當時聽到也是醉了,所以我要用心學習Web,其實這裏面蘊含的設計模式、算法、架構思想在源碼中體現的淋漓盡致啊,一個大寶庫竟然視而不見可惜了。下面就一起品味…

1.靜態代理

不要被這個設計模式高大上的名字給嚇到了,其實靜態代理還是挺容易理解的,用生活場景來理解靜態代理就是:託人辦事。假如一個公司想辦一場演唱會,要找明星去哪找呢?明星的經紀人啊,明星哪有時間來和公司談啊。所以這個經紀人就是靜態代理中的重要角色。來看一張UML圖,看看這其中的道理:
這裏寫圖片描述
其中Target可以理解爲明星,TargetInterface可以理解爲明星出場延長的標準,TargetProxy可以理解爲經紀人。經紀人按照明星出場的標準和公司談價格和其他事項等等。

將以上的思想用到Web中假如有這樣一個場景:刪除或者修改用戶信息,在這個過程中需要開啓事務。用靜態代理模擬這個場景。
這裏寫圖片描述
這次的代理對象就變成了UserDAOImpl了,而UserDAOProxy就成了上面的經紀人了(代理)。
具體代碼:GitHub
其實說到這裏靜態代理還是有很大的缺點的就是如果明星多了,我的經紀人成倍的增長,這個時候代碼量太大了。爲了克服這個問題纔有動態代理的產生。

2.動態代理

靜態代理可以說是動態代理的通俗版,動態代理要解決明星多了,經紀人(代理)增多的現象,同時優化代碼的效率。思想是差不多的,關鍵在用代碼實現的時候差距還是挺大的。動態代理在Java中一般有JDK代理(JDK本身提供的功能)、Cglib代理、AspectJ等。
具體代碼實現看這裏 。下面將和靜態代理的區別拉出來:

public class ProxyInterceptor implements InvocationHandler {
    //代理目標
    private Object target ;

    //引入事務
    private Transaction tx ;

    public ProxyInterceptor(Object target,Transaction tx) {
        this.target = target ;
        this.tx =  tx ;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        //開啓事務
        this.tx.beginTransaction(); 

        method.invoke(target, args);

        //提交事務
        this.tx.commitTransaction();
        return null;
    }

}

其中private Object target ;聲明爲Object類型表示可以接受任何類型的代理對象(各種各樣的明星)這樣就解決了,動態代理中的固定代理對象的問題。同時代理(經紀人)都要實現一個接口InvocationHandler 這個接口是幹嘛的呢?按照意思理解就是事件的處理者,然後重寫接口中的invoke方法,且不管方法中的參數是什麼,在這裏理解爲代理處理事務的重要方法。業務都在這個方法中進行調用。就可以實現了。這樣動態代理就解決了應對代理對象多樣性的問題。那麼什麼是AOP 呢?

3.面向切面編程的AOP

什麼是AOP呢?有了上面代理的基礎用一個例子就可以講解什麼是面向切面編程AOP了。案例背景:現在要取錢,取錢的過程之前ATM機器要開啓日誌功能、事務功能、安全性檢查等等。代碼在這裏。下面看最重要的代理對象:

package org.kylin.aop;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
 * @author UniKyln
 * @date 下午11:30:19 2015年3月31日
 * @blog:http://blog.csdn.net/unikylin
 * @github:https://github.com/unikylin/
 * @description 動態代理類
 */
public class DrawManagerProxy implements InvocationHandler {

    //代理目標類
    private Object target ; 

    //面向切面編程中的各種切面
    private Logger logger ;
    private Security security ;
    private Transaction tx ;

    public DrawManagerProxy(Object target,Logger logger,Security security,Transaction tx) {
        this.target = target ;
        this.logger = logger ;
        this.security = security ;
        this.tx = tx ;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        //啓動日誌
        this.logger.logger();

        //啓動事務
        this.tx.beginTransaction();

        //啓動安全性檢查
        this.security.checkSecurity();

        //取錢
        method.invoke(target, args);

        //提交事務
        this.tx.commitTransaction();

        return null;
    }   
}

在取錢之前啓動了日誌、開啓事務,然後提交事務。可以用下面一個圖來理解這個過程是如何發生的?
這裏寫圖片描述
上一篇文章已經提到這個圖了。可以理解執行方法之前的日誌記錄、事務、安全性框架都是AOP中的切面,而AOP中的通知可以理解爲是事務中的開啓事務、提交事務這兩個方法(切面中的方法可以理解爲通知)。所以可以發現事務、日誌、安全性框架和取錢完全是沒有耦合的,完全是靠代理類來實現業務的。在實際的開發中每個人開發每個人的功能,類似於安全性框架的開發可以獨立開發,及時以後去取錢之後需要打印小票,也可以增加一個切面實現這個功能。然後用AOP切面的思想將這些整合在一起形成一個完整的程序。

4.Struts2應用的AOP設計思想

先來看看Struts2的總體架構圖:
這裏寫圖片描述

從圖中可以發現很多的Interceptor,並且這些攔截器在Struts2中地位非常重要,這些攔截器就可以理解爲切面,而ActionProxy就相當於代理將這些攔截器和目標方法聯繫到一起。事實上Struts2的攔截器設計就是採用AOP實現的,而且Struts2和Spring整合的時候異常的處理和攔截也是使用AOP思想實現的。AOP已經深入到框架的核心設計理念中了。今天就講這麼多吧,下一節談談Servlet並且如何用Servlet原生API寫一個小小的類似於Struts2的框架,簡化web開發中遇到的問題。


非常高興和大家交流學習
自由轉載,創意許可,請註明文章來源,來自這裏
(http://blog.csdn.net/unikylin)

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