[設計模式]Proxy代理模式

1.定義

給某個對象提供一個代理對象,由代理對象控制對原對象的引用。java

區別:

1.適配器模式:適配器模式改變對象的接口,代理模式不改變接口。node

2.裝飾器模式:裝飾者模式是爲了增長功能,代理模式是爲了控制。ide

image

2.使用場景

1.中介隔離:隔離訪問,原對象不能被直接引用時,代理對象能夠經過實現相同的接口來間接提供給客戶訪問。函數

2.功能加強:擴展原對象的功能。主要負責預處理,過濾,過後對返回結果的處理。好比日誌功能,解決亂碼問題。工具

3.使用方法

按代理建立的時期,分爲靜態代理,動態代理。測試

靜態代理是在源碼上建立,並對其編譯。this

動態代理是在程序運行時,經過反射機制動態建立。代理

注意:代理對象不須要實現接口,可是目標對象必定要實現接口,不然不能用動態代理

3.1 靜態代理

1.建立服務接口日誌

public interface Machine {

    void run();
}

2.建立原對象code

public class RealMachine implements Machine {

    private String machineName;

    public RealMachine(String machineName){
        this.machineName = machineName;
        init();
    }

    @Override
    public void run() {

        System.out.println("run " + machineName);
    }

    private void init(){
        System.out.println("init "+machineName);
    }

}

3.建立代理對象

public class ProxyMachine implements Machine{

    private RealMachine realMachine;

    private String machineName;

    public ProxyMachine(String machineName){
        this.machineName = machineName;
    }

    @Override
    public void run() {

        if(realMachine == null){
            realMachine = new RealMachine(machineName);
        }

        System.out.println("start run");
        realMachine.run();
        System.out.println("stop run");

    }
}

4.測試

@Test
    public void testStaticMachine(){

        Machine machine = new ProxyMachine("robot 001");

        machine.run();
    }

靜態代理總結

每個原對象都要建立一個代理類,不適合

3.2 動態代理

1.建立動態代理類

public class DynamicProxyHandler implements InvocationHandler{

    private Object object;

    public DynamicProxyHandler(final Object object){
        this.object = object;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        System.out.println("start proxy run");

        Object invoke = method.invoke(object, args);

        System.out.println("stop proxy run");

        return invoke;
    }
}

2.測試

@Test
    public void testDynamicMachine(){

        Machine machine = new RealMachine("robot 002");

        Machine proxyMachine = (Machine) Proxy.newProxyInstance(
                Machine.class.getClassLoader(), new Class[]{Machine.class}, new DynamicProxyHandler(machine));

        proxyMachine.run();

    }

動態代理總結

代理包:java.lang.reflect.Proxy

JDK動態代理須要使用newProxyInstance方法.

static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h )

三個參數:

1.ClassLoader loader: 指定當前目標對象使用類加載器,獲取加載器的方法是固定的

2.Class<?>[] interfaces: 目標對象實現的接口的類型,使用泛型方式確認類型

3.InvocationHandler h 事件處理,執行目標對象的方法時,會觸發事件處理器的方法,會把當前執行目標對象的方法做爲參數傳入

3.3 代理工廠

1.建立代理工廠

public class ProxyFactory {

    private Object object;

    public ProxyFactory(Object object){
        this.object = object;
    }

    public Object getProxyInstance(){

        return Proxy.newProxyInstance(
                object.getClass().getClassLoader(),
                object.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                        System.out.println("start proxyFactory");
                        Object invoke = method.invoke(object, args);
                        System.out.println("stop proxyFactory");

                        return invoke;
                    }
                }
        );

    }

}

2.測試

@Test
    public void testProxyFactory(){

        Machine machine = new RealMachine("robot 003");

        Machine proxyInstance = (Machine) new ProxyFactory(machine).getProxyInstance();

        proxyInstance.printMessage("test");
    }

3.4 cglib代理工廠

和JDK代理不一樣,當目標對象沒有實現任何接口時,cglib代理能夠對目標對象進行代理。

cglib代理,又名子類代理。它是在內存中構建一個子類對象,從而實現對目標對象功能的擴展。

1.依賴包

asm-2.2.3,asm-commons-2.2.3,asm-util-2.2.3 ,cglib-nodep-2.1_3

2.建立實體

public class CglibMachine{

    private RealMachine realMachine;

    private String machineName;

    public CglibMachine(){

    }

    public CglibMachine(String machineName){
        this.machineName = machineName;
    }


    public void run() {

        if(realMachine == null){
            realMachine = new RealMachine(machineName);
        }

        System.out.println("start run");
        realMachine.run();
        System.out.println("stop run");

    }


}

3.建立工廠

public class CglibProxyFactory implements MethodInterceptor{

    private Object object;

    public CglibProxyFactory(Object object){
        this.object = object;
    }


    //給目標對象建立一個代理對象
    public Object getProxyInstance(){
        //工具類
        Enhancer enhancer = new Enhancer();
        //設置父類
        enhancer.setSuperclass(object.getClass());
        //設置回調函數
        enhancer.setCallback(this);
        //建立子類
        return enhancer.create();
    }


    @Override
    public Object intercept(Object target, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {

        System.out.println("start cglib proxy");

        //執行目標對象方法
        Object invoke = method.invoke(object, args);

        System.out.println("stop cglib proxy");

        return invoke;
    }
}

4.測試

@Test
    public void testCglibFactory(){

        CglibMachine machine = new CglibMachine("robot 004");

        CglibMachine proxyInstance = (CglibMachine) new CglibProxyFactory(machine).getProxyInstance();

        proxyInstance.run();

    }
相關文章
相關標籤/搜索