美文网首页
结构型-代理模式

结构型-代理模式

作者: 钉某人 | 来源:发表于2017-11-18 13:52 被阅读0次

源码地址|https://github.com/DingMouRen/DesignPattern

代理模式:在不改变原始类代码的情况下,通过引入代理类来给原始类附加功能。

静态代理类

在不改变原始类(或叫被代理类)的情况下,通过引入代理类来给原始类附加功能。一般情况下,我们让代理类和原始类实现同样的接口。但是,如果原始类并没有定义接口,并且原始类代码并不是我们开发维护的。在这种情况下,我们可以通过让代理类继承原始类的方法来实现代理模式。


/**
 * 抽象接口
 */
public interface Manager {

    void doSomething();
}

/**
 * 被代理类
 */
public class Admin implements Manager{
    @Override
    public void doSomething() {
        System.out.println("Admin--doSomething");
    }
}

/**
 * 代理类
 */
public class AdminProxy1 implements Manager {

    private Admin admin;

    public AdminProxy1(Admin admin) {
        this.admin = admin;
    }

    @Override
    public void doSomething() {
        System.out.println("adminProxy1 -- doSomething");
        admin.doSomething();
    }
}

/**
 * 代理类
 */
public class AdminProxy2 implements Manager {

    private Admin admin;

    public AdminProxy2(Admin admin) {
        this.admin = admin;
    }

    @Override
    public void doSomething() {
        System.out.println("adminProxy2 -- doSomething");
        admin.doSomething();
    }
}

/**
 * 使用类
 */
public class Client {

    public static void main(String[] args) {
        Admin admin = new Admin();

        //代理1执行
        AdminProxy1 adminProxy1 = new AdminProxy1(admin);
        adminProxy1.doSomething();

        //代理2执行
        AdminProxy2 adminProxy2 = new AdminProxy2(admin);
        adminProxy2.doSomething();
    }
}

缺点:静态代理中,需要将被代理类中所有的方法实现一遍,并且为每个方法附加相似的代码逻辑;另外如果要添加的附加功能
的类有多个,需要针对每个类创建一个代理类,增加维护成本。

动态代理

不用事先为每个原始类编写代理类,而是在运行的时候,动态的创建原始类对应的代理类,然后在系统中庸代理类替换原始类。
Java 语言本身就已经提供了动态代理的语法。

/**
 * 抽象接口
 */
public interface Moveable {

    void move();
}

/**
 * 被代理类
 */
public class Car implements Moveable {
    @Override
    public void move() {
        System.out.println("汽车行驶中...");
    }
}

/**
 * 事务处理器
 */
public class TimeHandler implements InvocationHandler {
    private Object target;

    public TimeHandler(Object target) {
        this.target = target;
    }


    /**
     *
     * @param proxy 被代理的对象
     * @param method 被代理对象的方法
     * @param args 方法参数
     * @return  方法返回值
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        long startTime = System.currentTimeMillis();
        System.out.println("汽车开始行驶");
        method.invoke(target,args);
        long stopTime = System.currentTimeMillis();
        System.out.println("汽车结束行驶");
        System.out.println("汽车行驶时间:"+(stopTime - startTime)+"毫秒");
        return null;
    }
}

/**
 * 使用类
 */
public class Client {
    public static void main(String[] args) {
        Car car = new Car();

        ClassLoader classLoader = car.getClass().getClassLoader();
        Class<?>[] clsArr = car.getClass().getInterfaces();
        InvocationHandler handler = new TimeHandler(car);

        Moveable moveable = (Moveable) Proxy.newProxyInstance(classLoader,
                                                    clsArr,
                                                    handler);
        moveable.move();
    }
}

cglib代理

cglib代理使用需要引入额外的jar包 cglib.jar

/**
 * 被代理类
 */
public class Train {
    public void move(){
        System.out.println("火车行驶中...");
    }
}

/**
 * 代理类
 */
public class CGLibProxy implements MethodInterceptor {
    private Enhancer enhancer = new Enhancer();

    public Object getProxy(Class<?> clazz){
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
        return enhancer.create();
    }

    /**
     * 拦截所有目标类方法的调用
     * @param obj 目标实例对象,被代理类
     * @param method 被代理类的反射对象
     * @param args 方法参数
     * @param methodProxy 代理类的实例
     * @return
     * @throws Throwable
     */
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println("日志开始");
        methodProxy.invokeSuper(obj,args);
        System.out.println("日志结束");
        return null;
    }
}


/**
 * 使用类
 */
public class Client {
    public static void main(String[] args) {
        CGLibProxy proxy = new CGLibProxy();
        Train train = (Train) proxy.getProxy(Train.class);
        train.move();
    }
}

代理模式的应用场景

  • 在业务系统中开发一些非功能性需求,比如:监控、统计、鉴权、限流、事务、日志等。我们将这些附加功能与业务功能解耦,放在代理类中统一处理,
  • 开发一个接口请求,一个支持缓存,一个支持实时查询。开发两个接口增加开发成本,应该是动态代理。如果是基于 Spring 框架来开发的话,那就可以在 AOP 切面中完成接口缓存的功能。在应用启动的时候,我们从配置文件中加载需要支持缓存的接口,以及相应的缓存策略(比如过期时间)等。当请求到来的时候,我们在 AOP 切面中拦截请求,如果请求中带有支持缓存的字段(比如http://…?..&cached=true),我们便从缓存(内存缓存或者 Redis 缓存等)中获取数据直接返回。

附:
静态代理需要代理类与被代理类同时实现接口
动态代理类需要被代理类实现接口
cglib不需要代理类或者被代理类实现接口

相关文章

  • Android进阶之光——设计模式(结构型设计模式)

    结构型设计模式 结构型设计模式是从程序的结构上解决模块之间的耦合问题 代理模式 代理模式也被称为委托模式。 定义:...

  • 【设计模式】结构型设计模式汇总

    结构型设计模式汇总 结构型设计模式名称 结构型设计模式主要包括 7 大类: 代理模式 桥接模式 装饰器模式 适配器...

  • Android设计模式——代理模式

    1.代理模式介绍 代理模式(Proxy Pattern),是七大结构型设计模式之一。 2.代理模式的定义 ...

  • 结构型模式

    简介 将类或对象按某种布局组成更大的结构。它分为类结构型模式和对象结构型模式。结构型模式分为:代理模式、适配器模式...

  • 14.代理模式(结构型)

    代理模式(结构型) 代理模式是常用的结构型设计模式之一,当无法直接访问某个对象或访问某个对象存在困难时可以通过一个...

  • 设计模式-代理模式

    代理模式介绍 代理模式(Proxy Pattern)也称为委托模式,是结构型设计模式的一种。在现实生活中用到代理的...

  • 设计模式-代理模式

    1.代理模式的介绍 代理模式(Proxy Pattern)也称为委托模式,是结构型设计模式的一种。在我们生活中代理...

  • 设计模式之代理模式(Proxy Pattern)

    代理模式简介 代理模式(Proxy Pattern)是结构型模式,这种模式为其他对象提供一种代理以控制对这个对象的...

  • 代理模式(Proxy Pattern)

    1. 简介 代理模式属于设计模式中的结构型模式,有静态代理和动态代理两种实现方式。代理模式使用代理类来控制访问委托...

  • 设计模式(六)代理模式

    1.代理模式简介 代理模式介绍 代理模式也叫委托模式,是结构型设计模式的一种。在现实生活中我们用到类似代理模式的场...

网友评论

      本文标题:结构型-代理模式

      本文链接:https://www.haomeiwen.com/subject/edpevxtx.html