[设计模式]Proxy代理模式

本文深入解析了代理模式的概念、使用场景及实现方法,包括静态代理、动态代理和CGLIB代理的详细步骤,以及如何通过代理模式增强对象功能。

1.定义

给某个对象提供一个代理对象,由代理对象控制对原对象的引用。

区别:

1.适配器模式:适配器模式改变对象的接口,代理模式不改变接口。

2.装饰器模式:装饰者模式是为了增加功能,代理模式是为了控制。

image

2.使用场景

1.中介隔离:隔离访问,原对象不能被直接引用时,代理对象可以通过实现相同的接口来间接提供给客户访问。

2.功能增强:扩展原对象的功能。主要负责预处理,过滤,事后对返回结果的处理。比如日志功能,解决乱码问题。

3.使用方法

按代理创建的时期,分为静态代理,动态代理。

静态代理是在源码上创建,并对其编译。

动态代理是在程序运行时,通过反射机制动态创建。

注意:代理对象不需要实现接口,但是目标对象一定要实现接口,否则不能用动态代理

3.1 静态代理

1.创建服务接口

public interface Machine {

    void run();
}

2.创建原对象

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();

    }

转载于:https://my.oschina.net/u/3371784/blog/2231526

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值