Java 代理模式详解

embedded/2024/10/31 1:48:09/

如果目标对象实现了接口,则默认采用 JDK 动态代理,否则采用 CGLIB 动态代理。

  1. 代理模式的定义
    • 代理模式是一种设计模式,它为其他对象提供一种代理,以控制对这个对象的访问。代理对象可以在客户端和目标对象之间起到中介的作用,它可以在不改变目标对象接口的情况下,增强目标对象的功能或者对目标对象的访问进行控制。
  1. 代理模式的结构
    • 主题(Subject)接口:定义了真实对象和代理对象共同的接口,客户端通过这个接口来访问真实对象和代理对象。例如,在一个文件读取系统中,主题接口可以是FileReaderSubject,它定义了读取文件内容的抽象方法,如readFile(String fileName)
    • 真实主题(Real Subject):实现了主题接口,是真正完成业务逻辑的对象。比如,在文件读取系统中,真实主题可以是FileReaderImpl,它实现了FileReaderSubject接口,具体实现了从文件系统中读取文件内容的方法。
    • 代理(Proxy):同样实现了主题接口,代理对象内部包含了真实主题对象的引用。它可以在调用真实主题对象的方法之前或之后,添加额外的逻辑,如权限验证、日志记录等。在文件读取系统中,代理对象FileReaderProxy可以在调用FileReaderImplreadFile方法之前,先检查用户是否有读取文件的权限。
  1. 代理模式的类型
    • 静态代理
// 接口定义
interface Calculator {int add(int a, int b);
}
// 真实主题(被代理类)
class CalculatorImpl implements Calculator {@Overridepublic int add(int a, int b) {return a + b;}
}
// 代理类
class CalculatorProxy implements Calculator {private Calculator calculator;public CalculatorProxy(Calculator calculator) {this.calculator = calculator;}@Overridepublic int add(int a, int b) {System.out.println("在加法运算前进行日志记录");int result = calculator.add(a, b);System.out.println("在加法运算后进行日志记录");return result;}
}
      • 定义:静态代理是在编译时期就已经确定了代理类和被代理类的关系。代理类和被代理类都需要实现同一个接口,代理类通过持有被代理类的实例来调用其方法,并在调用前后添加自己的逻辑。
      • 示例:假设我们有一个接口Calculator,它有一个方法add(int a, int b)用于计算两数之和。
      • 在这个例子中,CalculatorProxyCalculatorImpl的代理类。当客户端调用CalculatorProxyadd方法时,它会先打印日志,然后调用CalculatorImpladd方法,最后再打印日志。
    • 动态代理
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
// 动态代理的调用处理器
class CalculatorInvocationHandler implements InvocationHandler {private Object target;public CalculatorInvocationHandler(Object target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("在动态代理方法调用前进行日志记录");Object result = method.invoke(target, args);System.out.println("在动态代理方法调用后进行日志记录");return result;}
}
Calculator calculator = new CalculatorImpl();
Calculator proxy = (Calculator) Proxy.newProxyInstance(Calculator.class.getClassLoader(),new Class[]{Calculator.class},new CalculatorInvocationHandler(calculator));
int result = proxy.add(1, 2);
      • 定义:动态代理是在运行时动态地生成代理类。在Java中,主要通过java.lang.reflect.Proxy类和InvocationHandler接口来实现动态代理。动态代理不需要像静态代理那样为每个被代理类都编写一个代理类,它可以根据需要动态地创建代理对象。
      • 示例:还是以上面的Calculator接口为例,我们可以这样实现动态代理:
      • 客户端使用动态代理的代码如下:
      • 在这个动态代理的例子中,CalculatorInvocationHandler是实现了InvocationHandler接口的调用处理器。Proxy.newProxyInstance方法会在运行时动态地生成一个代理对象,这个代理对象实现了Calculator接口。当客户端调用代理对象的方法时,会触发InvocationHandlerinvoke方法,在这个方法中可以添加代理逻辑,如日志记录,然后再调用真实对象(CalculatorImpl)的方法。
  1. 代理模式的应用场景
    • 远程代理:用于访问远程对象,就好像访问本地对象一样。例如,在分布式系统中,客户端通过代理对象来调用远程服务器上的对象。代理对象负责处理网络通信等细节,如Java RMI(Remote Method Invocation)就使用了远程代理。
    • 虚拟代理:当创建一个对象的代价比较大(如加载大型资源文件、初始化复杂对象等)时,可以使用虚拟代理。虚拟代理先创建一个简单的代理对象来代替真实对象,当真正需要使用真实对象时,再进行创建。例如,在网页加载图片时,可以先显示一个占位符(代理),当图片真正加载完成后(真实对象创建完成),再显示真实的图片。
    • 安全代理:用于控制对敏感对象的访问。代理对象可以在访问真实对象之前,对用户的权限进行验证。例如,在企业级应用中,对某些敏感数据的访问,只有具有特定权限的用户才能通过代理访问到真实的数据。


http://www.ppmy.cn/embedded/133764.html

相关文章

基于uniapp微信小程序的宠物救助宠物领养系统

作者:计算机学姐 开发技术:SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等,“文末源码”。 专栏推荐:前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏:…

【计网】网络协议栈学习总结 --- 浏览器上输入网址域名后点击回车,到底发生了什么?

未来的路不会比过去更笔直,更平坦, 但是我并不恐惧, 我眼前还闪动着道路前方野百合和野蔷薇的影子。 --- 季羡林 《八十抒怀》--- 浏览器上输入URL后回车,到底发生了什么? 1 前言2 解析URL形成http请求3 DNS域名解…

60V恒流IC SL8443B内置功率MOS 支持2.5A电流 降压LED恒流驱动芯片

一、概述 SL8443B是一款高性能的LED恒流驱动芯片,具有60V的耐压能力,适用于高电压应用场景。它内置了5A(或说5V,根据上下文理解为功率等级)的功率MOS,可以减少外部元件数量,降低成本&#xff0…

基于微信小程序的图书馆座位预约系统+LW示例参考

系列文章目录 1.基于SSM的洗衣房管理系统原生微信小程序LW参考示例 2.基于SpringBoot的宠物摄影网站管理系统LW参考示例 3.基于SpringBootVue的企业人事管理系统LW参考示例 4.基于SSM的高校实验室管理系统LW参考示例 5.基于SpringBoot的二手数码回收系统原生微信小程序LW参考示…

利用EasyExcel实现简易Excel导出

目标 通过注解形式完成对一个方法返回值的通用导出功能 工程搭建 pom <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance&qu…

vue组件在项目中的常用业务逻辑(1)

若要使用一个组件&#xff08;已有基本结构&#xff09; 1.在api>index.js获取接口数据&#xff08;这里是模拟数据&#xff09; 2.去vuex仓库&#xff08;store>home.js&#xff09;存储数据&#xff08;state mutations actions三连环&#xff09; &#xff08;准备…

如何解决前端发送数据到后端为空的问题

在进行前后端交互时&#xff0c;经常会遇到前端发送数据到后端时数据为空的问题。本文将详细探讨如何解决这一问题&#xff0c;并提供具体的解决方案。 问题描述 在前后端交互过程中&#xff0c;前端通过 axios 发送数据到后端&#xff0c;但在后端接收时发现数据为空。这可能…

第十五章 Vue工程化开发及Vue CLI脚手架

目录 一、引言 二、Vue CLI 基本介绍 三、安装Vue CLI 3.1. 安装npm和yarn 3.2. 安装Vue CLI 3.3. 查看 Vue 版本 四、创建启动工程 4.1. 创建项目架子 4.2. 启动工程 五、脚手架目录文件介绍 六、核心文件讲解 6.1. index.html 6.2. main.js 6.3. App.vue 一、…