美文网首页
设计模式之代理模式

设计模式之代理模式

作者: Catch6 | 来源:发表于2022-01-26 19:01 被阅读0次

代理模式是一种结构型设计模式。结构型模式主要总结了一些类或对象组合在一起的经典结构,这些经典的结构可以解决特定应用场景的问题。结构型模式包括:代理模式、桥接模式、装饰器模式、适配器模式、门面模式、组合模式、享元模式。

代理模式的应用场景

  • 业务系统的非功能性需求开发。比如:监控、统计、鉴权、限流、事务、幂等、日志。我们将这些附加功能与业务功能解耦,放到代理类中统一处理,让程序员只需要关注业务方面的开发。
  • RPC、缓存中应用。RPC 框架也可以看作一种代理模式;假设我们要开发一个接口请求的缓存功能,对于某些接口请求,如果入参相同,在设定的过期时间内,直接返回缓存结果,而不用重新进行逻辑处理。

代理模式分为静态代理和动态代理。静态代理的代理对象,在程序编译时已经写好 Java 文件了,直接 new 一个代理对象即可。动态代理产生代理对象的时机是运行时动态生成,它没有 Java 源文件,直接生成字节码文件实例化代理对象。

静态代理的实现有两种:通过接口和通过继承。

静态代理 - 通过接口方式

类图

代码实现

UserService

public interface UserService {

    public Boolean login(String username, String password);

}

UserServiceImpl

public class UserServiceImpl implements UserService {

    @Override
    public Boolean login(String username, String password) {
        return "admin".equals(username) && "admin".equals(password);
    }

}

UserServiceProxy

public class UserServiceProxy implements UserService {

    private final UserService userService;

    public UserServiceProxy(UserService userService) {
        this.userService = userService;
    }

    @Override
    public Boolean login(String username, String password) {
        long t1 = System.nanoTime();
        System.out.println("start login");
        Boolean result = userService.login(username, password);
        System.out.println("end login");
        long t2 = System.nanoTime();
        System.out.println("time: " + (t2 - t1) + "ns");
        return result;
    }

}

Main

public class Main {

    public static void main(String[] args) {
        UserService userService = new UserServiceProxy(new UserServiceImpl());
        Boolean result = userService.login("admin", "admin");
        System.out.println("result: " + result);
    }

}

静态代理 - 通过继承方式

类图

代码实现

UserService

public interface UserService {

    public Boolean login(String username, String password);

}

UserServiceImpl

public class UserServiceImpl implements UserService {

    @Override
    public Boolean login(String username, String password) {
        return "admin".equals(username) && "admin".equals(password);
    }

}

UserServiceProxy

public class UserServiceProxy extends UserServiceImpl {

    @Override
    public Boolean login(String username, String password) {
        long t1 = System.nanoTime();
        System.out.println("start login");
        Boolean result = super.login(username, password);
        System.out.println("end login");
        long t2 = System.nanoTime();
        System.out.println("time: " + (t2 - t1) + "ns");
        return result;
    }

}

Main

public class Main {

    public static void main(String[] args) {
        UserService userService = new UserServiceProxy();
        Boolean result = userService.login("admin", "admin");
        System.out.println("result: " + result);
    }

}

动态代理

上面的代码实现有两个问题:

  1. 我们需要在代理类中,将原始类中的所有的方法,都重新实现一遍,并且为每个方法都附加相似的代码逻辑。
  2. 如果要添加的附加功能的类有不止一个,我们需要针对每个类都创建一个代理类。

这时我们就需要用到动态代理(Dynamic Proxy),就是我们不事先为每个原始类编写代理类,而是在运行的时候,动态地创建原始类对应的代理类,然后在系统中用代理类替换掉原始类。

如何实现动态代理呢?

Java 语言本身就已经提供了动态代理的语法(实际上,动态代理底层依赖的就是 Java 的反射语法)。

类图

UserService

public interface UserService {

    public Boolean login(String username, String password);

}

UserServiceImpl

public class UserServiceImpl implements UserService {

    @Override
    public Boolean login(String username, String password) {
        return "admin".equals(username) && "admin".equals(password);
    }

}

DynamicProxyHandler

public class DynamicProxyHandler implements InvocationHandler {

    private Object target;

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

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        long t1 = System.nanoTime();
        System.out.println("start " + target.getClass().getName() + ":" + method.getName());
        Object result = method.invoke(target, args);
        System.out.println("end " + target.getClass().getName() + ":" + method.getName());
        long t2 = System.nanoTime();
        System.out.println("time: " + (t2 - t1) + "ns");
        return result;
    }

}

DynamicProxy

public class DynamicProxy {

    public Object createProxy(Object target) {
        ClassLoader classLoader = target.getClass().getClassLoader();
        Class<?>[] interfaces = target.getClass().getInterfaces();
        DynamicProxyHandler handler = new DynamicProxyHandler(target);
        return Proxy.newProxyInstance(classLoader, interfaces, handler);
    }

}

Main

public class Main {

    public static void main(String[] args) {
        DynamicProxy proxy = new DynamicProxy();
        UserService userService = (UserService) proxy.createProxy(new UserServiceImpl());
        Boolean result = userService.login("admin", "admin");
        System.out.println("result: " + result);
    }

}

至此,我们已经实现了基于JDK的动态代理,JDK动态代理要求要代理的类必须实现接口,如果类没有实现接口,那么你可以尝试 CGLIB,它不是JDK自带的,而是第三方类库,感兴趣可以详细了解。

相关文章

  • 设计模式之代理模式

    设计模式之代理模式 10分钟看懂动态代理设计模式(升级篇)-对这篇动态代理模式的思路整理 仿JDK实现动态代理逻辑...

  • 代理模式

    设计模式之代理模式 什么是代理模式? 指的事代理对象为其他对象提供代理以控制对被...

  • Java设计模式之代理模式

    Java设计模式之代理模式 代理模式 静态代理 动态代理 为什么需要代理 通过代理,我们能够不用知道委托人是谁,而...

  • Java代理模式之JDK动态代理

    了解什么是动态代理模式,可参考Java设计模式之代理模式 简介 JDK动态代理是java.lang.reflect...

  • 设计模式之代理模式2

    设计模式之代理模式运用 代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对...

  • 设计模式之代理模式

    设计模式之代理模式 简介 代理模式是结构型设计模式。 当无法或不想直接访问某个对象或访问某个对象存在困难时可以通过...

  • 设计模式之代理模式

    title: 设计模式之代理模式date: 2018-08-15 20:25:42tags: 设计模式 笔记 Ja...

  • java设计模式之代理模式(静态代理)

      今天给大家分享的是java设计模式之代理模式中的静态代理模式,动态代理模式将在后面文章中给出。如有不足,敬请指...

  • Android 代理模式

    Android 设计模式系列文章 Android 23种设计模式 前言 代理模式可能是我们平时开发中最常见的模式之...

  • 设计模式之代理模式

    设计模式之代理模式 1.代理模式的定义 为其他对象提供一种代理以控制对这个对象的访问. 2.代理模式的使用场景 当...

网友评论

      本文标题:设计模式之代理模式

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