java中的設計模式——代理模式,通過動態代理實現AOP

    代理模式的定義:爲其他對象提供一種代理以控制對這個對象的訪問。在某些情況下,一個對象不適合或者不能直接引用另一個對象,而代理對象可以在客戶端和目標對象之間起到中介的作用。

    動態代理:

    舉個簡單的例子

1. 模式的結構
代理模式的主要角色如下。
抽象主題(Subject)類:通過接口或抽象類聲明真實主題和代理對象實現的業務方法。
真實主題(Real Subject)類:實現了抽象主題中的具體業務,是代理對象所代表的真實對象,是最終要引用的對象。
代理(Proxy)類:提供了與真實主題相同的接口,其內部含有對真實主題的引用,它可以訪問、控制或擴展真實主題的功能。

public interface BaseSubject {
    void request();
}

實現類:
public class RealSubject implements BaseSubject {
    @Override
    public void request() {
        System.out.println("realSubject");
    }
}

代理類

public class ProxyClassOfRealSubject implements BaseSubject{
    private RealSubject realSubject;
    @Override
    public void request() {
        before();
        realSubject.request();
        after();
    }
    public void before(){
        System.out.println("before  ,do something");
    }
    public void after(){
        System.out.println(" after ,do something");
    }
}

然後
通過創建代理類對象來訪問真實想訪問的RealSubject

 public static void main(String[] args) {
        ///代理類訪問
  }


public class UserDao {
    public void addUser(){
        System.out.println("添加用戶");
    }
    public void deleteUser(){
        System.out.println("刪除用戶");
    }
}

創建代理類CglibProxy,該代理類需要實現MethodInterceptor接口,並實現接口中的intercept()方法。

//代理類
public class CglibProxy implements MethodInterceptor {
    //代理方法
    public Object createProxy(Object target){
        //創建一個動態類對象
        Enhancer enhancer=new Enhancer();
        //確定要增強的類,設置其父類
        enhancer.setSuperclass(target.getClass());
        //添加回調函數
        enhancer.setCallback(this);
        //返回創建的代理類
        return enhancer.create();
    }
    /**
     * proxy CGlib根據父類生成的代理對象
     * method 攔截的方法
     * args 攔截方法的參數組
     * methodProxy 方法的代理對象,用於執行父類的方法
     */
    @Override
    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        //創建切面類對象
        MyAspect myAspect=new MyAspect();
        //前增強
        myAspect.check_Permissions();
        //目標方法執行
        Object obj=methodProxy.invokeSuper(proxy,args);
        //後增強
        myAspect.log();
        return obj;
    }
}

測試類 CglibTest.java

public class CglibTest {
    public static void main(String[] args){
        //創建代理類對象
        CglibProxy cglibProxy=new CglibProxy();
        //創建目標對象
        UserDao userDao=new UserDao();
        //獲取增強後的目標對象
        UserDao userDao1=(UserDao) cglibProxy.createProxy(userDao);
        //執行方法
        userDao1.addUser();
        userDao1.deleteUser();
    }
}	

 
代理模式的應用場景
    前面分析了代理模式的結構與特點,現在來分析以下的應用場景。
    遠程代理,這種方式通常是爲了隱藏目標對象存在於不同地址空間的事實,方便客戶端訪問。例如,用戶申請某些網盤空間時,會在用戶的文件系統中建立一個虛擬的硬盤,用戶訪問虛擬硬盤時實際訪問的是網盤空間。
    虛擬代理,這種方式通常用於要創建的目標對象開銷很大時。例如,下載一幅很大的圖像需要很長時間,因某種計算比較複雜而短時間無法完成,這時可以先用小比例的虛擬代理替換真實的對象,消除用戶對服務器慢的感覺。
    安全代理,這種方式通常用於控制不同種類客戶對真實對象的訪問權限。
    智能指引,主要用於調用目標對象時,代理附加一些額外的處理功能。例如,增加計算真實對象的引用次數的功能,這樣當該對象沒有被引用時,就可以自動釋放它。
    延遲加載,指爲了提高系統的性能,延遲對目標的加載。例如,Hibernate 中就存在屬性的延遲加載和關聯表的延時加載。
代理模式的擴展
    在前面介紹的代理模式中,代理類中包含了對真實主題的引用,這種方式存在兩個缺點。
    真實主題與代理主題一一對應,增加真實主題也要增加代理。
    設計代理以前真實主題必須事先存在,不太靈活。採用動態代理模式可以解決以上問題,如 SpringAOP
在軟件設計中,使用代理模式的例子也很多,例如,要訪問的遠程對象比較大(如視頻或大圖像等),其下載要花很多時間。還有因爲安全原因需要屏蔽客戶端直接訪問真實對象,如某單位的內部數據庫等。
代理模式的定義與特點
代理模式的定義:由於某些原因需要給某對象提供一個代理以控制對該對象的訪問。這時,訪問對象不適合或者不能直接引用目標對象,代理對象作爲訪問對象和目標對象之間的中介。

代理模式的主要優點有:
代理模式在客戶端與目標對象之間起到一箇中介作用和保護目標對象的作用;
代理對象可以擴展目標對象的功能;
代理模式能將客戶端與目標對象分離,在一定程度上降低了系統的耦合度;

其主要缺點是:
在客戶端和目標對象之間增加一個代理對象,會造成請求處理速度變慢;
增加了系統的複雜度;
代理模式的結構與實現
代理模式的結構比較簡單,主要是通過定義一個繼承抽象主題的代理來包含真實主題,從而實現對真實主題的訪問,下面來分析其基本結構和實現方法。

JDK動態代理和cglib代理

JDK動態代理有缺陷,就是被代理對象必須實現接口才能產生代理對象,如果沒有接口,就不能使用動態代理技術。我們用spring容器來實現動態代理,假如要管理的對象沒有實現接口,那麼就不能產生代理對象了。爲了讓所有的對象都能產生動態代理對象,Spring又融入了第三方代理技術cglib代理。Cglib可以對任何類生成代理對象,它的原理是對目標對象進行繼承代理,如果目標對象被final修飾,那麼該類無法被cglib代理。

如果被代理對象實現了接口,就優先使用JDK代理,如果沒有實現接口,就用用cglib代理。

如果想代理沒有實現接口的類,那麼可以使用CGLIB代理.
CGLIB(Code Generation Library)是一個高性能開源的代碼生成包,它採用非常底層的字節碼技術,對指定的目標類生成一個子類,並對子類進行增強。
 

 

 

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