1. 程式人生 > >java中的代理模式與spring中的AOP

java中的代理模式與spring中的AOP

1.java的代理模式

代理(proxy)是一種設計模式,是屬於23種常見設計模式中的一種。談到設計模式,我們首先想到的是設計模式的幾大原則,其中談論最多的還是單一職責和開閉原則,代理模式實現了對目標物件其他的訪問方式,即通過代理物件(proxy)訪問目標物件(target)。這樣一來,我們可以在目標物件實現的基礎上,通過代理物件來對目標物件的功能擴充套件,它很好地闡釋了開閉原則,即對程式的擴充套件開放,對程式的修改關閉的原則。
代理模式在我們生活當中經常遇見,比如租客與房東收房租的關係,房東是房子擁有者,他可以自己帶租客看房子,談價錢等等。但如果房間太多,房東一個人完成不了這麼多工作,那麼他會聘請中介來幫助他完成這一系列動作,房東只負責籤合同和收房費。這時候代理模式就產生了,房東是目標物件,中介就是代理物件。
此時,代理模式的主要角色為:目標物件、代理物件。代理物件是對目標物件的擴充套件,並會呼叫該目標物件
    -

1.1靜態代理

靜態代理在實現時,需要定義相關介面或者父類,被代理物件與代理物件一起實現相同的介面或者是繼承相同父類

還是以上面的房屋出為例:兩個角色分別為房東(Owner)和中介(Agency),他們共同實現介面Rent
Rent介面如下:

/**
 * 介面
 */
public interface Rent {
    //出租房屋
    void rent();
}

目標物件:Owner

/**
 * 介面實現
 * 目標物件
 */
public class Owner implements Rent {
    //重寫rent方法
    public void
rent() { System.out.println("房東出租房屋"); } } 代理物件:Agency

/**
* 代理物件,靜態代理
*/
public class Agency implements Rent{
//接收儲存目標物件
private Owner owner;
public Agency (Owner owner ){
this.owner =owner ;
}

public void rent() {
owner.rent();//執行目標物件的方法
}
}

測試方法:
/**
 * 測試類
 */
public class Test {
    public static void main(String[] args) {
        //目標物件
        Owner owner= new Owner();

        //代理物件,把目標物件傳給代理物件,建立代理關係
        Agency agency= new Agency(owner);

        agency.rent();//執行的是代理的方法
    }
}

以上就實現了靜態代理案例,它達到了在不修改目標物件的功能前提下,對目標功能擴充套件,符合了開閉原則,但是如果一旦需要增加介面方法,目標物件與代理物件都要新增相應的程式碼,這又與開閉原則相違背,那麼如何解決如上問題呢?接下來就看動態代理模式

1.2 動態代理

2.1 動態代理的特點
1、代理物件不用實現相關介面
2、代理物件的生成,是通過利用JDK的API,動態的在記憶體中構建代理物件(僅需要我們指定建立代理物件/目標物件實現的介面的型別即可)

2.2代理物件生成的相關API
需要用到的類:java.lang.reflect.Proxy
JDK實現代理需要使用newProxyInstance()這個方法,但是該方法需要接收三個引數,具體的實現是:
static Object newProxyInstance(ClassLoader loader, Class

/**
 * 建立動態代理物件
 * 動態代理不需要實現介面,但是需要指定介面型別
 */
public class ProxyFactory{

    //維護一個目標物件
    private Object target;
    public ProxyFactory(Object target){
        this.target=target;
    }

   //給目標物件生成代理物件
    public Object getProxyInstance(){
        return Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("操作1");
                        //執行目標物件方法
                        Object returnValue = method.invoke(target, args);
                        System.out.println("操作2");
                        return returnValue;
                    }
                }
        );
    }

}

可以編寫測試類來測試:

/**
 * 測試類
 */
public class Test {
    public static void main(String[] args) {
        // 目標物件
        IUserDao target = new UserDao();

        System.out.println(target.getClass());

        // 給目標物件,建立代理物件
        Agency agency= (Agency) new ProxyFactory(Owner).getProxyInstance();
        // class $Proxy0   記憶體中動態生成的代理物件
        System.out.println(agency.getClass());

        // 執行方法   【代理物件】
        agency.rent();
    }
}

以上就是Java的動態代理,總結:Java動態代理物件不需要實現介面,但是目標物件(Owner物件)一定要實現介面,否則不能用動態代理

spring中的AOP

AOP和IOC組成了spring的重要兩大思想,AOP即面向切面程式設計,它應用於專案中的日誌功能,許可權管理,事物等等。這些功能程式碼都直接切入地在該物件層次中,而與它對應的物件的核心程式碼沒有關係,這種散佈在各處的無關的程式碼被稱為橫切(cross cutting)。剖解開封裝的物件內部,並將那些影響了多個類的公共行為封裝到一個可重用模組,並將其命名為”Aspect”,即切面。切面與業務無關,卻為業務模組所共同呼叫的邏輯或責任封裝起來,便於減少系統的重複程式碼,降低模組之間的耦合度,並有利於未來的可操作性和可維護性。

使用”橫切”技術,AOP把軟體系統分為兩個部分:核心關注點和橫切關注點。業務處理的主要流程是核心關注點,與之關係不大的部分是橫切關注點。橫切關注點的一個特點是,他們經常發生在核心關注點的多處,而各處基本相似,比如許可權認證、日誌、事物。AOP的作用在於分離系統中的各種關注點,將核心關注點和橫切關注點分離開來。