設計模式-代理模式

一、代理模式基本概述

代理模式給某一個對象提供一個代理對象,並由代理對象控制對原對象的引用。通俗的來講代理模式就是我們生活中常見的中介。

二、代理模式的優勢

1、解耦

2、功能擴展

三、代理模式的分類

1、靜態代理:由程序員創建或由特定工具自動生成源代碼,再對其編譯。在程序運行前,代理類的.class文件就已經存在了。

2、動態代理:在程序運行時,運用反射機制動態創建而成。

四、靜態代理和動態代理的區別

靜態代理通常只能代理一個類,而動態代理是代理一個接口下的多個實現類

靜態代理實現知道要代理的是什麼,而動態代理不知道要代理什麼東西,只有在運行的時候才知道

五、靜態代理代碼案列

package com.sheting.reflect.proxy.staticproxy;

import java.util.Date;

//接口
public interface HelloService {

    String echo(String msg);

    Date getTime();
}

package com.sheting.reflect.proxy.staticproxy;

import java.util.Date;

//實現類
public class HelloServiceImpl implements HelloService {
    @Override
    public String echo(String msg) {
        return "echo:" + msg;
    }

    @Override
    public Date getTime() {
        return new Date();
    }
}

package com.sheting.reflect.proxy.staticproxy;

import java.util.Date;

//代理類
public class HelloServiceProxy implements HelloService {
    //表示被代理的HelloService 實例
    private HelloService helloService;

    public HelloServiceProxy(HelloService helloService) {
        this.helloService = helloService;
    }

    public void setHelloServiceProxy(HelloService helloService) {
        this.helloService = helloService;
    }

    @Override
    public String echo(String msg) {
        //預處理
        System.out.println("before calling echo()");
        //調用被代理的HelloService 實例的echo()方法
        String result = helloService.echo(msg);
        //事後處理
        System.out.println("after calling echo()");
        return result;
    }

    @Override
    public Date getTime() {
        //預處理
        System.out.println("before calling getTime()");
        //調用被代理的HelloService 實例的getTime()方法
        Date date = helloService.getTime();
        //事後處理
        System.out.println("after calling getTime()");
        return date;
    }
}


 六、JDK動態代理案列

/**
 * @author: xuWei
 * @create: 2019/12/19
 * 接口
 */
public interface People {
    public void sayHello();
}

/**
 * @program: demo
 * @author: xuWei
 * @create: 2019/12/19
 * @description:實現類
 */
public class PeopleImpl implements People {

    @Override
    public void sayHello() {
        System.out.println("chinesse say hello");
    }
}

/**
 * @program: demo
 * @author: xuWei
 * @create: 2019/12/19
 * @description:代理類
 */
public class PeopleInvocationHandler implements InvocationHandler {

    private Object target;

    public Object getTarget(Object target) {
        this.target = target;
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("記錄日誌開始");
        Object invoke = method.invoke(target, args);
        System.out.println("記錄日誌結束");
        return invoke;
    }
}

八、Cglib動態代理

/**
 * @program: demo
 * @author: xuWei
 * @create: 2019/12/19
 * @description:Cglib動態代理類
 */
public class CglibDynamisProxy implements MethodInterceptor {

    private Object target;

    public Object getInstance(Object target){
        this.target=target;
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(this.target.getClass());
        enhancer.setCallback(this);
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("記錄日誌開始");
        Object invoke = methodProxy.invokeSuper(o,objects);
        System.out.println("記錄日誌結束");
        return invoke;
    }
}

九、JDK動態代理和Cglib動態代理的區別?

JDK動態代理利用反射機制實現一個代理接口的匿名類,如果目標對象實現了接口,默認情況下采用JDK代理

Cglib動態代理,將代理對象的class文件加載進來,通過修改字節碼生成子類來處理,覆蓋其中的方法,因爲是繼承,所以目標對象的類或方法最好不要聲明成final

十、JDK爲什麼不能針對類生成代理?

由於java的單繼承,動態生成的代理類已經繼承了Proxy類的,就不能再繼承其他的類,所以只能靠實現被代理類的接口的形式,故JDK的動態代理必須有接口。

發佈了66 篇原創文章 · 獲贊 7 · 訪問量 9158
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章