Spring-AOP代理模式

  • 為其他對象提供一種代理,以控制對這個對象的訪問。

一、代理模式分類

  • 1、遠程代理:為不同地理的對象,提供局域網(wǎng)代表對象(類似于客戶端和服務(wù)器端)
  • 2、虛擬代理:根據(jù)需要將消耗資源很大的對象進行延遲,真正需要的時候進行創(chuàng)建。(網(wǎng)頁中 圖片的加載,先用一張?zhí)摂M的圖片進行顯示,等圖片加載完成后再進行顯示)
  • 3、保護代理:控制用戶的訪問權(quán)限。(注冊成功后才能發(fā)帖)
  • 4、智能應用代理:提供對目標對象一些額外的服務(wù)。(火車站)

二、靜態(tài)代理

  • 代理和被代理對象在代理之前是確定的,實現(xiàn)了相同的接口或抽象類
  • 靜態(tài)代理實現(xiàn)方式:繼承和聚合
    繼承:創(chuàng)建一個類(代理類)繼承被代理類(實現(xiàn)相同的接口),在代理類中調(diào)用父類的被代理方法,在方法的前后增加代理的業(yè)務(wù)邏輯
public class Car implements Moveable {
    
    @Override
    public void move() {
    
        try {
            Thread.sleep(new Random().nextInt(1000));
            System.out.println("汽車行駛中。。。");
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
public class Car2 extends Car {

    @Override
    public void move() {
        long starttime=System.currentTimeMillis();
        System.out.println("汽車開始行駛。。。");
        super.move();
        long endtime=System.currentTimeMillis();
        System.out.println("汽車結(jié)束行駛。。。"+"用時:"+
        (endtime-starttime)+"毫秒");
    }   
}

聚合:一個類中調(diào)用另一個類的對象(兩者實現(xiàn)相同接口)。在代理類中聲明被代理類的對象,并通過構(gòu)造方法將對象傳進來(初始化)。在代理類的接口方法中調(diào)用被代理類對象的方法,并在方法前后增加相應代理業(yè)務(wù)邏輯。

public class Car3 implements Moveable {

    private Car car;
    
    public Car3(Car car) {
        super();
        this.car = car;
    }

    @Override
    public void move() {
        long starttime=System.currentTimeMillis();
        System.out.println("汽車開始行駛。。。");
        car.move();
        long endtime=System.currentTimeMillis();
        System.out.println("汽車結(jié)束行駛。。。"+"用時:"+
        (endtime-starttime)+"毫秒");
    }
}

在創(chuàng)建一個日志代理,

public class CarLogProxy implements Moveable {

    private Moveable m;
    
    public CarLogProxy(Moveable m) {
        super();
        this.m = m;
    }

    @Override
    public void move() {
        System.out.println("日志開始");
        m.move();
        System.out.println("日志結(jié)束");
    }
}
        Car car=new Car();
        CarTimeProxy ctp=new CarTimeProxy(car);
        CarLogProxy clp=new CarLogProxy(ctp);
        clp.move();
                /*
                *日志開始
                *汽車開始行駛。。。
                *汽車行駛中。。。
                *汽車結(jié)束行駛。。。用時:137毫秒
                *日志結(jié)束
                */

當想要先輸出汽車行駛代理,在輸出日志代理,只需要更改main方法中代理的順序即可。

三、動態(tài)代理

Paste_Image.png
Paste_Image.png
  • 動態(tài)代理步驟
    1、創(chuàng)建一個類,實現(xiàn)InvocationHandler接口,并實現(xiàn)invoke方法,添加業(yè)務(wù)邏輯(實現(xiàn)原有功能并添加額外功能)
    2、創(chuàng)建被代理的類以及接口
    3、調(diào)用Proxy的靜態(tài)方法newProxyInstance(loader, interfaces, h)
    4、通過代理調(diào)用方法
public class TimeHandler implements InvocationHandler {

    private Object target;
    
    public TimeHandler(Object target) {
        super();
        this.target = target;
    }
    /*
     * proxy:被代理的對象
     * method:被代理對象的方法
     * args:方法的參數(shù)
     * 返回值:調(diào)用方法的返回值
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        long starttime=System.currentTimeMillis();
        System.out.println("汽車開始行駛。。。");
        method.invoke(target);
        long endtime=System.currentTimeMillis();
        System.out.println("汽車結(jié)束行駛。。。"+"用時:"+
        (endtime-starttime)+"毫秒");
        return null;
    }
}

創(chuàng)建接口

public interface Moveable {
    public void move(); 
}

實現(xiàn)接口類

public class Car implements Moveable {
    
    @Override
    public void move() {
    
        try {
            Thread.sleep(new Random().nextInt(1000));
            System.out.println("汽車行駛中。。。");
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

調(diào)用Proxy的靜態(tài)方法

public class Test {
    /*
     * 動態(tài)代理測試類
     */
    public static void main(String[] args) {
        Car car=new Car();
        InvocationHandler h=new TimeHandler(car);
        ClassLoader loader=car.getClass().getClassLoader();
        Class[] interfaces=car.getClass().getInterfaces();
        /*
         * loader:被代理類的類加載器
         * interfaces:實現(xiàn)的接口
         * h:InvocationHandler實現(xiàn)
         */
        Moveable m=(Moveable) Proxy.newProxyInstance(loader, interfaces, h);
        m.move();
    }
}

四、CGLIB代理

  • 針對類來實現(xiàn)的代理
  • 對指定目標類產(chǎn)生一個子類,通過方法攔截技術(shù)攔截所有父類方法的調(diào)用
public class CglibProxy implements MethodInterceptor {
    //創(chuàng)建代理類屬性
    private Enhancer enhance=new Enhancer();
    //傳遞需要代理的類
    public Object getProxy(Class clazz){
        //設(shè)置創(chuàng)建子類的類
        enhance.setSuperclass(clazz);
        enhance.setCallback(this);
        
        return enhance.create();
    }

    /*
     * 攔截所有目標類方法的調(diào)用
     * obj:目標類的實例
     * m:目標方法的返回對象
     * args:方法的參數(shù)
     * proxy:代理類實例
     */
    @Override
    public Object intercept(Object obj, Method m, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("日志開始。。。");
        //代理類調(diào)用父類方法
        proxy.invokeSuper(obj, args);
        System.out.println("日直結(jié)束。。。");
        return null;
    }
}
        CglibProxy proxy=new CglibProxy();
        Train t=(Train) proxy.getProxy(Train.class);
        t.move();
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容