Java静态代理设计模式深度解析:原理、应用及实现

全文目录:

    • 开篇语
    • 前言
    • 摘要
    • 概述
    • 源码解析
      • 1. 定义公共接口
      • 2. 创建实际业务类
      • 3. 创建代理类
    • 使用案例分享
      • 案例:权限校验功能
    • 应用场景案例
    • 优缺点分析
      • 优点
      • 缺点
    • 核心类方法介绍
    • 测试用例
    • 小结
    • 总结
    • 文末

开篇语

哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云/阿里云/华为云/51CTO;欢迎大家常来逛逛

  今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。

  我是一名后端开发爱好者,工作日常接触到最多的就是Java语言啦,所以我都尽量抽业余时间把自己所学到所会的,通过文章的形式进行输出,希望以这种方式帮助到更多的初学者或者想入门的小伙伴们,同时也能对自己的技术进行沉淀,加以复盘,查缺补漏。

小伙伴们在批阅的过程中,如果觉得文章不错,欢迎点赞、收藏、关注哦。三连即是对作者我写作道路上最好的鼓励与支持!

前言

在Java开发中,设计模式是提升代码可读性、复用性和维护性的关键手段之一。上期我们探讨了面向对象编程中的单例模式,深入分析了其实现方式和实际应用。然而,面对复杂的系统结构,仅靠单例模式难以应对各类需求,因此引入了代理模式来增强代码的灵活性。本期将聚焦静态代理设计模式,这是一种通过代理对象代替实际对象完成任务的设计方式,在解耦业务逻辑和增强代码功能方面尤为重要。

静态代理模式作为代理模式的一种实现方式,结构简单,应用广泛。本文将从静态代理模式的原理入手,结合源码解析、具体应用案例,逐步深入其应用场景和优缺点分析。通过本篇内容,读者将全面掌握静态代理设计模式的核心思想,并能够在实际开发中灵活运用。

摘要

本文旨在为读者详细介绍Java开发中的静态代理设计模式。我们将从静态代理的概述开始,逐步解析其实现过程,通过源码解析和使用案例展现静态代理的应用。接着,深入分析静态代理在各类场景中的实战应用,并总结其优缺点,最后通过具体测试用例验证代理的工作效果。通过学习静态代理设计模式,开发者能更好地在系统中实现模块解耦,提升代码复用性。

概述

静态代理是一种在编译期就实现代理类的设计模式,通过代理类对目标对象进行功能扩展。代理类和被代理类实现同样的接口,代理类在调用方法前后添加了额外的功能(例如权限校验、日志记录等)。这种模式常用于希望对既有功能进行增强的场景,是Spring AOP框架的基础之一。

静态代理模式的核心在于设计代理类和实际业务类共同实现同一接口,代理类调用实际业务类的功能并加以增强。这种设计使得代理类可以不直接改变实际业务代码而实现额外功能。

源码解析

在Java中实现静态代理需要三个主要元素:接口、目标类和代理类。以下是一个简单的静态代理模式实现源码。

1. 定义公共接口

首先定义一个公共接口Service,其中包含了一个serve方法:

public interface Service {void serve();
}

2. 创建实际业务类

RealService类实现了Service接口,定义了具体的业务逻辑。

public class RealService implements Service {@Overridepublic void serve() {System.out.println("RealService is serving...");}
}

3. 创建代理类

ServiceProxy类同样实现了Service接口,并在serve方法中调用RealServiceserve方法,同时可以加入额外的功能:

public class ServiceProxy implements Service {private RealService realService;public ServiceProxy(RealService realService) {this.realService = realService;}@Overridepublic void serve() {System.out.println("Logging before service...");realService.serve();System.out.println("Logging after service...");}
}

在该示例中,代理类ServiceProxy在执行目标对象RealServiceserve方法前后增加了日志记录功能,从而实现了不改变实际业务类的增强效果。

使用案例分享

在实际开发中,静态代理模式广泛用于功能增强,例如权限控制、日志记录、性能统计等场景。以下以一个权限校验案例展示静态代理的应用。

案例:权限校验功能

假设我们需要对服务的使用进行权限校验,可以通过在代理类中加入权限检查逻辑。

public class PermissionServiceProxy implements Service {private RealService realService;private String userRole;public PermissionServiceProxy(RealService realService, String userRole) {this.realService = realService;this.userRole = userRole;}@Overridepublic void serve() {if ("ADMIN".equals(userRole)) {System.out.println("Permission granted.");realService.serve();} else {System.out.println("Permission denied.");}}
}

通过此设计,PermissionServiceProxy类在调用serve方法时,会根据用户角色判断权限,避免了直接在业务逻辑中硬编码权限逻辑。

应用场景案例

静态代理设计模式在各类实际开发中有广泛应用,以下列举几个典型场景:

  1. 日志记录:代理类在调用实际业务方法前后进行日志记录,帮助开发者跟踪方法调用情况。
  2. 性能监控:可以在方法调用前后统计执行时间,评估性能瓶颈。
  3. 权限控制:通过代理判断用户权限,确保业务方法只能被授权用户访问。
  4. 事务管理:在数据库操作的前后加入事务开启、提交或回滚操作,确保数据一致性。

优缺点分析

优点

  1. 代码解耦:代理模式将业务逻辑和功能增强分离,便于后期维护。
  2. 复用性高:代理类可以应用于多个实际业务类,避免了重复代码。
  3. 结构清晰:使用代理模式增强功能,不会直接修改实际业务类,提高代码结构清晰度。

缺点

  1. 类数量增多:每个业务类需要一个代理类,代码量增大。
  2. 扩展性受限:由于代理类是在编译期生成的,难以动态调整代理逻辑,不适用于复杂业务逻辑。

核心类方法介绍

在静态代理模式中,核心方法主要集中在代理类的设计上:

  • serve(): 代理类和目标类的共有方法,用于实际业务处理。代理类在该方法中调用目标类的serve()方法,同时可以添加增强功能。
  • before() / after(): 在代理类中自定义的增强方法,用于处理目标方法执行前后的额外逻辑,如日志记录、权限校验等。

测试用例

测试静态代理的关键在于验证代理类的增强功能是否生效,以下是一个简单的测试用例:

public class StaticProxyTest {public static void main(String[] args) {// 实例化目标对象RealService realService = new RealService();// 创建代理对象并传入目标对象ServiceProxy proxy = new ServiceProxy(realService);// 调用代理对象的方法proxy.serve();}
}

输出结果应为:

Logging before service...
RealService is serving...
Logging after service...

通过该测试用例,可以验证代理类是否在方法调用前后添加了日志记录,确保了增强功能的正确性。

小结

本文详细解析了静态代理设计模式的核心概念,展示了如何在Java开发中通过静态代理实现代码增强。通过多个应用案例,读者可以看到静态代理在权限控制、日志记录等场景中的灵活应用。同时,本文还对静态代理的优缺点、核心方法、测试用例进行了详尽分析,使开发者在实际开发中能够有针对性地选择静态代理模式来提升系统功能。

总结

静态代理设计模式是一种结构清晰、实现简单的代码增强方式。虽然其扩展性相对动态代理稍显不足,但在实际开发中,通过静态代理实现的日志记录、权限控制、性能监控等功能具有高度可复用性,能够显著提升代码质量。在未来的开发中,建议在适用场景中优先考虑静态代理,既能提升系统的安全性和可靠性,也有助于代码的维护和扩展。

… …

文末

好啦,以上就是我这期的全部内容,如果有任何疑问,欢迎下方留言哦,咱们下期见。

… …

学习不分先后,知识不分多少;事无巨细,当以虚心求教;三人行,必有我师焉!!!

wished for you successed !!!


⭐️若喜欢我,就请关注我叭。

⭐️若对您有用,就请点赞叭。

⭐️若有疑问,就请评论留言告诉我叭。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/58354.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大数据选型对比追命连环50问及参考答案

在面试时,考官很喜欢问选型的问题,考察面试者知识广度和深度。因为在实际企业开发项目,选型是很关键的一步,如果选错了,挖的坑可能要大量的时间去填了。特别是出现严重问题需要重新选择大数据组件,就意味着要推倒重来。。。而老板是不喜欢这种没产出的投入。 目录 详细…

Linux——常见指令及其权限理解(正在更新中)

1.指令 1.1 快速了解指令 pwd 首次登录,默认所处的路径 whoami 当前所用的用户的名称 ls 显示当前路径下,文件名称 mkdir 在当前目录下,创建一个文件夹/目录 cd 进入一个目录 touch 新建一个文…

esp32 GPIO 分别用5种中断类型控制LED

下面程序分别用ANYEDGE POSEDGE NEGEDGE HIGH_LEVEL LOW_LEVEL 中断类型控制GPIO 0 脚的电平。此程序的重点是用延时消除按键产生的无用中断信号 硬件 1. led 接0脚和地 2. 按钮接gpio 1脚 和地或3.3v 脚 图片 程序 #include "driver/gpio.h" #incl…

ansible开局配置-openEuler

ansible干啥用的就不多介绍了,这篇文章主要在说ansible的安装、开局配置、免密登录。 ansible安装 查看系统版本 cat /etc/openEuler-latest输出内容如下: openeulerversionopenEuler-24.03-LTS compiletime2024-05-27-21-31-28 gccversion12.3.1-30.…

金蝶云星空采购退料单集成易仓出库单实现高效数据对接

金蝶云星空采购退料单集成易仓出库单实现高效数据对接 Done-金蝶-采购退料单——>易仓-出库单:高效数据集成方案解析 在企业的日常运营中,数据的准确传递和实时处理至关重要。本文将聚焦于一个具体的系统对接集成案例:如何将金蝶云星空中…

基于Ubuntu24.04,下载并编译Android12系统源码 (二)

1. 前言 上篇文章,我们基于Ubuntu24.04,已经成功下载下来了Android12的源码,这篇文章我们会接着上文,基于Ubuntu24.04来编译Android源码。 2. 编译源码 2.1 了解源码编译的名词 Makefile : Android平台的一个编译系…

CMake 生成器表达式介绍

【写在前面】 生成器表达式在构建系统生成期间进行评估&#xff0c;以生成特定于每个构建配置的信息。它们的形式为 $<...>。例如&#xff1a; target_include_directories(tgt PRIVATE /opt/include/$<CXX_COMPILER_ID>) 这将扩展为 “/opt/include/GNU”、“/opt…

CV项目整理

1. 爬取+展示的实时项目 1.1 核心技术 myqls + maxwell + redis+django 实现读写分离,实时项目,主从复制,读写分离,顺写日志。 maxwell将自己伪装成为slave,就可以从Mysql的集群中获取顺写日志Binlog maxwell取得的数据格式json 1.2 流程 1.3优化查询 下面的查询,笛卡尔…

如何通过sip信令以及抓包文件分析媒体发到哪个地方

前言 问题描述&#xff1a;A的媒体没转发到B&#xff0c;B只能听到回铃音&#xff0c;没有A的说话声音&#xff0c;并且fs这边按正常的信令发送了. 分析流程 分析早期媒体发送到哪一个IP 10.19.0.1发送了一个请求给10.19.0.157这个IP&#xff0c;然而这里的SDP媒体地址&am…

Flink(一)

目录 架构处理有界与无界数据部署应用到任意地方运行任意规模应用利用内存性能 流应用流处理应用的基本组件流状态时间 应用场景事件驱动应用事件驱动应用的优势Flink如何支持事件驱动应用&#xff1f; 典型的事件驱动示例 数据分析应用流式分析应用的优势&#xff1f;Flink 如…

RabbitMQ 安装(Windows版本)和使用

安装 安装包获取 可以自己找资源&#xff0c;我这里也有百度云的资源&#xff0c;如果没失效的话可以直接用。 通过百度网盘分享的文件&#xff1a;RabbitMQ 链接&#xff1a;https://pan.baidu.com/s/1rzcdeTIYQ4BqzHLDSwCgyw?pwdfj79 提取码&#xff1a;fj79 安装教程…

Pr 视频效果:闪光灯

视频效果/风格化/闪光灯 Stylize/Strobe Light 闪光灯 Strobe Light效果可用于在视频中创建闪烁或频闪的效果&#xff0c;类似于舞台上的频闪灯或摄影中的闪光灯。 ◆ ◆ ◆ 效果选项说明 通过调整各种参数&#xff0c;可以自定义闪光的颜色、频率、持续时间和混合模式&#…

深入理解ThreadLocal底层原理

ThreadLocal是线程私有的&#xff0c;各个线程之间是隔离的。可以想象一下每次线程创建的时候在堆上预先分配一个内存空间用于存储ThreadLocal的数据。 &#xff08;1&#xff09;当线程被创建时&#xff0c;线程都会有一个成员变量ThreadLocalMap。 //每个线程定义一个成员变…

GCC之编译(7)Linker链接脚本

GCC之(7)Linker链接脚本 Author: Once Day Date: 2024年10月25日 一位热衷于Linux学习和开发的菜鸟&#xff0c;试图谱写一场冒险之旅&#xff0c;也许终点只是一场白日梦… 漫漫长路&#xff0c;有人对你微笑过嘛… 本文档翻译自GNU LD链接脚本官方手册 参考文章: GNU LD …

OpenCV中的坐标运算 [C#]

在C#语言中&#xff0c;可以使用OpenCV库进行坐标运算&#xff0c;包括平移、缩放、点到点的距离和点到线的距离。 从Nuget下载 OpenCvSharp4.Windows 下面是一些示例代码&#xff1a; 点到点的距离&#xff1a; using OpenCvSharp;/// <summary> /// 点到点距离 /// …

windows命令汇总

windows命令汇总 1. 查看注册表的值 reg query “HKLM\Software\YourSoftwareKey” /v YourValueName 举例 reg query “HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters” /v MaxUserPort reg query “HKEY_LOCAL_MACHINE\SYSTEM\Current…

构建自然灾害预警决策一体化平台,筑牢工程安全数字防线

近年来&#xff0c;国家和部委也强调了要切实加强地质灾害监测预警。作为国内智慧应急领域的先行者&#xff0c;Mapmost持续探索利用数字孪生技术&#xff0c;推进自然灾害风险预警精细化&#xff0c;强化对监测数据的综合分析和异常信息研判处置。建立健全区域风险预警与隐患点…

Redis中Lua脚本的使用场景

Redis 中的 Lua 脚本可以用于多种场景&#xff0c;以下是一些常见的使用场景及其对应的 Java 实现示例。 通过使用 Lua 脚本&#xff0c;可以在 Redis 中实现复杂的逻辑和原子操作&#xff0c;同时利用 Java 客户端&#xff08;如 Spring Data Redis&#xff09;方便地执行这些…

使用 Qt GRPC 构建高效的 Trojan-Go 客户端:详细指南

使用 Qt GRPC 构建高效的 Trojan-Go 客户端&#xff1a;详细指南 初识 Qt 和 gRPC 什么是 Qt&#xff1f;什么是 gRPC&#xff1f; 项目结构概述创建 proto 文件定义 API 下载 api.proto 文件解析 proto 文件 1. package 与 option 语句2. 消息类型定义 TrafficSpeedUserUserSt…

CI/CD 的原理

一、CI/CD 的概念 CI/CD是一种软件开发流程&#xff0c;旨在通过自动化和持续的集成、测试和交付实现高质量的软件产品。 CI(Continuous Integration)持续集成 目前主流的开发方式是协同开发&#xff0c;即多位开发人员同事处理同意应用不同模块或功能。 如果企业在同一时间将…