Java 代理模式的基本概念、使用场景、应用示例和实现方法

这篇具有很好参考价值的文章主要介绍了Java 代理模式的基本概念、使用场景、应用示例和实现方法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

代理模式是一种常见的设计模式,在 Java 开发中被广泛应用。它允许我们通过添加一个代理对象来控制对另一个对象的访问,从而提供了一种间接访问实际对象的方法。本文将详细介绍 Java 代理模式的基本概念、使用场景、应用示例和实现方法等相关内容。

1. 概述

代理模式是一种结构型设计模式,它允许我们通过添加一个代理对象来控制对另一个对象的访问。代理对象和实际对象具有相同的接口,使得客户端在不知情的情况下可以使用代理对象进行操作。代理对象在与客户端进行交互时,可以控制对实际对象的访问,以实现一些额外的功能,例如访问计数、延迟加载、权限控制等。

在 Java 中,代理模式主要有两种实现方式:静态代理和动态代理。静态代理需要手动编写代理类,通常需要针对每个实际对象编写一个代理类,在系统中管理多个代理类比较麻烦。而动态代理则可以在运行时动态生成代理类,使得客户端代码更加简洁和易于维护。本文将分别介绍这两种代理模式的实现方法和使用场景。

2. 静态代理

静态代理是最基本的代理模式,它需要手动编写代理类。在 Java 中,可以通过实现或继承相同的接口或父类,使得代理对象拥有与实际对象相同的方法和属性。代理对象在调用实际对象的方法时,可以在方法前或方法后添加一些额外的操作,以实现特定的功能。

2.1 实现方式

假设我们需要实现一个简单的计算器程序,我们首先需要定义一个计算器接口:

public interface Calculator {
    int add(int a, int b);
    int sub(int a, int b);
    int mul(int a, int b);
    int div(int a, int b);
}

然后,我们可以实现一个实际的计算器类:

public class RealCalculator implements Calculator {
    @Override
    public int add(int a, int b) {
        return a + b;
    }

    @Override
    public int sub(int a, int b) {
        return a - b;
    }

    @Override
    public int mul(int a, int b) {
        return a * b;
    }

    @Override
    public int div(int a, int b) {
        if (b == 0) {
            throw new IllegalArgumentException("除数不能为零");
        }
        return a / b;
    }
}

接下来,我们可以编写一个代理类来控制对计算器对象的访问:

public class CalculatorProxy implements Calculator {
    private final Calculator calculator;
    
    public CalculatorProxy(Calculator calculator) {
        this.calculator = calculator;
    }

    @Override
    public int add(int a, int b) {
        System.out.println("执行加法操作");
        return calculator.add(a, b);
    }

    @Override
    public int sub(int a, int b) {
        System.out.println("执行减法操作");
        return calculator.sub(a, b);
    }

    @Override
    public int mul(int a, int b) {
        System.out.println("执行乘法操作");
        return calculator.mul(a, b);
    }

    @Override
    public int div(int a, int b) {
        System.out.println("执行除法操作");
        return calculator.div(a, b);
    }
}

在上面的代码中,我们使用一个 CalculatorProxy 类来代理计算器对象。当客户端调用代理类的方法时,代理类会通过实际对象来真正执行计算操作。在代理类的方法前或方法后,可以添加一些额外的操作,例如日志记录、性能监控等。

2.2 使用场景

静态代理适用于以下情况:

  • 对象创建和销毁比较频繁,例如数据库连接池等场景;
  • 在调用实际对象的方法前或方法后需要添加一些额外的操作,例如日志记录、性能监控等;
  • 对象需要在不同的环境中进行不同的处理,例如权限控制、事务管理等。

2.3 实现方式

静态代理的实现方式比较简单,但也存在一些问题。首先,由于代理类需要手动编写,因此无法应对复杂的对象结构;其次,代理类与实际对象存在强耦合关系,当实际对象发生变化时需要修改代理类;最后,为每个实际对象编写一个代理类会增加系统中类的数量,使得系统变得更加复杂和难以维护。

3. 动态代理

动态代理是一种更加灵活和高效的代理模式,它可以在运行时动态生成代理类,避免了手动编写大量代理类的繁琐工作。在 Java 中,动态代理主要有两种实现方式:JDK 动态代理和 CGLIB 动态代理。

3.1 JDK 动态代理

JDK 动态代理是 Java 标准库提供的一种动态代理实现方式,它基于接口代理实现。在 JDK 动态代理中,我们需要通过 java.lang.reflect.Proxy 类来生成代理对象。

假设我们还是需要一个计算器程序,我们可以重新定义一个计算器接口:

public interface Calculator {
    int add(int a, int b);
    int sub(int a, int b);
    int mul(int a, int b);
    int div(int a, int b);
}

然后,我们可以使用 JDK 动态代理来生成代理对象:

public class CalculatorInvocationHandler implements InvocationHandler {
    private final Object target;

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

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("执行方法前");
        Object result = method.invoke(target, args);
        System.out.println("执行方法后");
        return result;
    }
}

public class Main {
    public static void main(String[] args) {
        Calculator calculator = new RealCalculator();
        CalculatorInvocationHandler handler = new CalculatorInvocationHandler(calculator);
        Calculator proxy = (Calculator) Proxy.newProxyInstance(
            calculator.getClass().getClassLoader(),
            calculator.getClass().getInterfaces(),
            handler);

        int a = 1, b = 2;
        System.out.println("add: " + proxy.add(a, b));
        System.out.println("sub: " + proxy.sub(a, b));
        System.out.println("mul: " + proxy.mul(a, b));
        System.out.println("div: " + proxy.div(a, b));
    }
}

在上面的代码中,我们定义了一个 CalculatorInvocationHandler 类来实现 java.lang.reflect.InvocationHandler 接口。当客户端调用代理对象的方法时,JDK 动态代理会自动调用 invoke 方法,并将原始方法的调用转发给 RealCalculator 对象。在 invoke 方法前或方法后,我们可以添加一些额外的操作,例如日志记录、性能监控等。

3.2 CGLIB 动态代理

CGLIB 动态代理是一种不基于接口的动态代理实现方式,它可以代理没有实现接口的类。在 CGLIB 动态代理中,我们需要通过 net.sf.cglib.proxy.Enhancer 类来生成代理对象。

假设我们有一个没有实现任何接口的类:

public class UserService {
    public void addUser(String username, String password) {
        System.out.println("add user: " + username + ", " + password);
    }

    public void updateUser(String username, String password) {
        System.out.println("update user: " + username + ", " + password);
    }

    public void deleteUser(String username) {
        System.out.println("delete user: " + username);
    }
}

然后,我们可以使用 CGLIB 动态代理来生成代理对象:

public class UserServiceInterceptor implements MethodInterceptor {
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("执行方法前");
        Object result = proxy.invokeSuper(obj, args);
        System.out.println("执行方法后");
        return result;
    }
}

public class Main {
    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(UserService.class);
        enhancer.setCallback(new UserServiceInterceptor());
        UserService proxy = (UserService) enhancer.create();

        proxy.addUser("Tom", "123456");
        proxy.updateUser("Tom", "654321");
        proxy.deleteUser("Tom");
    }
}

在上面的代码中,我们定义了一个 UserServiceInterceptor 类来实现 net.sf.cglib.proxy.MethodInterceptor 接口。当客户端调用代理对象的方法时,CGLIB 动态代理会自动调用 intercept 方法,并将原始方法的调用转发给 UserService 类。在 intercept 方法前或方法后,我们可以添加一些额外的操作,例如日志记录、性能监控等。

3.3 使用场景

动态代理适用于以下情况:

  • 对象结构比较复杂,手动编写代理类比较困难;
  • 需要对多个对象进行代理操作,手动编写代理类比较繁琐;
  • 在不修改实际对象的情况下添加一些额外的功能,例如日志记录、性能监控等。

4. 总结

代理模式是一种非常常用的设计模式,它可以通过添加一个代理对象来控制对另一个对象的访问。在 Java 中,代理模式主要有两种实现方式:静态代理和动态代理。

静态代理需要手动编写代理类,通常需要针对每个实际对象编写一个代理类,在系统中管理多个代理类比较麻烦。而动态代理则可以在运行时动态生成代理类,使得客户端代码更加简洁和易于维护。

JDK 动态代理基于接口代理实现,适用于需要代理接口的场景;而 CGLIB 动态代理不基于接口,并且可以代理没有实现接口的类。动态代理适用于对象结构比较复杂、需要对多个对象进行代理操作或需要添加一些额外的功能的场景。

无论是静态代理还是动态代理,代理对象和实际对象都应该具有相同的接口,使得客户端可以使用代理对象进行操作。代理对象在与客户端进行交互时,可以控制对实际对象的访问,以实现一些额外的功能,例如访问计数、延迟加载、权限控制等。文章来源地址https://www.toymoban.com/news/detail-743325.html

到了这里,关于Java 代理模式的基本概念、使用场景、应用示例和实现方法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Java SPI概念、实现原理、优缺点、应用场景、使用步骤、实战SPI案例

    在当今互联网时代,应用程序越来越复杂,对于我们开发人员来说,如何实现高效的组件化和模块化已经成为了一个重要的问题。而 Java SPI (Service Provider Interface)机制,作为一种基于接口的服务发现机制,可以帮助我们更好地解决这个问题。这样会程序具有高度的 灵活性、

    2024年02月13日
    浏览(47)
  • 状态设计模式(State Pattern)[论点:概念、相关角色、图示、示例代码、框架中的运用、适用场景]

            状态模式 (State Pattern)是一种行为型设计模式,用于解决对象在不同状态下的行为问题。它允许一个对象在其内部状态改变时改变它的行为。状态模式主要包含三个部分: 上下文 (Context)、 状态接口 (State)和 具体状态实现类 (ConcreteState)。 状态接口(St

    2023年04月14日
    浏览(45)
  • 命令设计模式(Command Pattern)[论点:概念、组成角色、相关图示、示例代码、框架中的运用、适用场景]

            命令设计模式 (Command Pattern)是一种行为设计模式,它将请求的操作封装为一个对象,从而实现请求者和执行者之间的解耦。这样,请求者只需要知道如何发送请求,而无需关心请求的具体执行过程。命令模式在很多场景下都非常有用,例如撤销操作、延迟执行、

    2024年02月01日
    浏览(50)
  • 【动态规划】动态规划算法基本概念,原理应用和示例代码

             动态规划(Dynamic Programming,简称DP)是一种解决多阶段决策问题的数学优化方法。它将原问题分解成若干个子问题,通过解决子问题只需解决一次并将结果保存下来,从而避免了重复计算,提高了算法效率。         通俗来讲,动态规划算法是解决一类具有重叠

    2024年01月21日
    浏览(49)
  • 观察者设计模式(Observer Design Pattern)[论点:概念、组成角色、相关图示、示例代码、框架中的运用、适用场景]

            观察者设计模式(Observer Design Pattern)是一种行为型设计模式,它定义了一种对象间的一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,当主题对象状态发生改变时,通知所有观察者对象,使它们能够自动更新。 主题(Subject):主题是一个抽象类或

    2023年04月24日
    浏览(46)
  • 【设计模式】builder 创建者设计模式详解(包含电商应用场景及代码示例)

    在常见的设计模式中,“Builder” 通常是指一种设计模式,而不是具体的类或方法。Builder 模式是一种创建型设计模式,其目的是通过提供一个独立的构建器类来构建一个复杂对象。 建造者模式 (Builder Pattern) 是一种创建型设计模式,它的主要目标是为了将一个复杂对象的构

    2024年01月21日
    浏览(49)
  • Java代理之jdk动态代理+应用场景实战

    本文将先介绍jdk动态代理的基本用法,并对其原理和注意事项予以说明。之后将以两个最常见的应用场景为例,进行代码实操。这两个应用场景分别是 拦截器 和 声明性接口 ,它们在许多开发框架中广泛使用。比如在spring和mybatis中均使用了拦截器模式,在mybatis中还利用动态

    2023年04月10日
    浏览(44)
  • Kafka核心设计与实践原理:设计理念、基本概念、主要功能与应用场景

    详细介绍Kafka作为分布式流式处理平台的设计理念、基本概念,以及其主要功能与应用场景,包括消息系统、容错的持久化、流式处理平台等功能,同时探讨如何保证消息的唯一性、消费顺序等问题。

    2024年02月22日
    浏览(48)
  • TensorFlow 的基本概念和使用场景

    TensorFlow 是 Google 开源的机器学习框架,它支持使用数据流图(Data Flow Graph)的方式进行计算,以实现大规模分布式机器学习应用。TensorFlow 在深度学习、自然语言处理、计算机视觉等领域有广泛应用。 TensorFlow 中的重要概念包括: 张量(Tensor):TensorFlow 中的基本数据类型,

    2024年02月11日
    浏览(39)
  • 【TensorFlow 的基本概念和使用场景。】

    TensorFlow 是一个开源的深度学习框架,由 Google 开发和维护。它提供了一个灵活且高效的方式来进行机器学习和人工智能任务的开发和部署。TensorFlow 的基本概念包括: 图(Graph):TensorFlow 使用图来表示计算任务。图是由节点(Nodes)和边(Edges)组成的,节点表示操作(或称

    2024年02月22日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包