10、【代理模式】通过引入一个代理对象来控制对原始对象的访问的方式。

你好,我是程序员雪球。

 

今天我们了解代理模式的原理、静态代理和动态代理的区别、Spring AOP 和动态代理的关系、代理模式的使用场景,以及用 Java 实现一个动态代理示例

 684f0c326cc94a1d9960930ae42d5419.png

 

一、代理模式的原理

 

代理模式是一种设计模式,它提供了一种通过引入一个代理对象来控制对原始对象的访问的方式。代理对象在客户端和原始对象之间充当中间人,它可以在调用原始对象的方法之前或之后执行额外的操作,如日志记录、缓存、权限检查等。

 

在代理模式中,有三个主要角色:

 

1. 抽象主题(Subject):定义了原始对象和代理对象的公共接口,包含了原始对象的所有方法。

2. 具体主题(ConcreteSubject):实现了抽象主题接口,是实际的业务逻辑对象。

3. 代理(Proxy):实现了抽象主题接口,它持有一个具体主题对象的引用,并在调用具体主题的方法时可以添加额外的逻辑。

 

代理对象通常通过组合或继承的方式来实现对原始对象的包装。在调用代理对象的方法时,它会将请求转发给原始对象,并可以在调用前后执行自定义的逻辑。

 

二、静态代理和动态代理的区别

 

静态代理是在编译时创建的代理类,它通过继承原始对象的类或实现其接口,并在其中重写需要代理的方法来实现。静态代理在运行时会生成一个新的类,因此它的性能可能会受到一定的影响。

 

动态代理是在运行时动态创建的代理类,它通过使用反射机制在运行时生成代理对象的字节码,并将其加载到 JVM 中。动态代理通常使用 Java 的反射 API 和动态字节码生成技术来实现,如 Java 的 Proxy 类或 CGLIB 库。动态代理的优点是不需要在编译时生成代理类,因此可以更加灵活地处理各种代理需求。

 

三、Spring AOP 和动态代理的关系

 

Spring AOP(Aspect-Oriented Programming,面向方面编程)是 Spring 框架提供的一种强大的横切关注点技术,它基于动态代理实现。通过 Spring AOP,我们可以在不修改原始代码的情况下,将横切关注点(如日志记录、事务管理、权限检查等)编织到业务逻辑代码中。

 

Spring AOP 使用了动态代理来创建代理对象,并在调用原始对象的方法时自动执行横切逻辑。Spring AOP 支持两种类型的动态代理:基于 JDK 的动态代理和基于 CGLIB 的动态代理。基于 JDK 的动态代理要求被代理的对象必须实现至少一个接口,而基于 CGLIB 的动态代理则不需要接口。

 

在 Spring AOP 中,我们可以通过配置 XML 文件或使用注解来定义切入点(Pointcut)和横切逻辑(Advice),Spring 会在运行时根据切入点和横切逻辑自动创建代理对象,并将其注入到应用的上下文中。

 

四、代理模式的使用场景

 

代理模式在以下场景中非常有用:

 

1. 远程调用(RPC):在分布式系统中,代理对象可以作为远程服务的本地代表,将远程方法调用转换为本地调用,并处理网络通信和序列化等细节。

2. 缓存:通过使用代理对象,可以在调用原始对象的方法之前或之后检查缓存中是否已经存在结果,并返回缓存中的结果,以提高系统性能。

3. 权限检查:代理对象可以在调用原始对象的方法之前进行权限检查,只有具备足够权限的用户才能访问受保护的资源。

4. 日志记录:通过代理对象,可以在调用原始对象的方法之前或之后记录日志信息,以便跟踪和审计系统的操作。

5. 事务管理:代理对象可以在调用原始对象的方法之前开始事务,在方法成功执行后提交事务,或者在发生异常时回滚事务,以保证数据的一致性。

 

五、用 Java 实现一个动态代理示例

 

以下是一个简单的 Java 动态代理示例,使用了 JDK 的动态代理机制来创建一个代理对象,它会在调用原始对象的方法前后打印日志信息:

 

 

import java.lang.reflect.InvocationHandler;

import java.lang.reflect.Method;

import java.lang.reflect.Proxy;

 

public class DynamicProxyExample {

 

    public static void main(String[] args) {

        // 创建一个原始对象

        HelloWorldImpl helloWorldImpl = new HelloWorldImpl();

 

        // 创建一个动态代理对象

        HelloWorldProxy helloWorldProxy = new HelloWorldProxy(helloWorldImpl);

 

        // 使用代理对象执行方法

        helloWorldProxy.sayHello();

    }

 

    // 原始对象的接口

    interface HelloWorld {

        void sayHello();

    }

 

    // 原始对象的实现类

    static class HelloWorldImpl implements HelloWorld {

        @Override

        public void sayHello() {

            System.out.println("Hello, World!");

        }

    }

 

    // 动态代理类

    static class HelloWorldProxy implements InvocationHandler {

        private HelloWorld helloWorld;

 

        public HelloWorldProxy(HelloWorld helloWorld) {

            this.helloWorld = helloWorld;

        }

 

        @Override

        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

            // 在调用方法之前打印日志信息

            System.out.println("Before method invocation: " + method.getName());

 

            // 调用原始对象的方法

            Object result = method.invoke(helloWorld, args);

 

            // 在调用方法之后打印日志信息

            System.out.println("After method invocation: " + method.getName());

 

            return result;

        }

    }

 

    // 使用 JDK 的动态代理机制创建代理对象

    public static Object createProxy(Object target, Class<?>[] interfaces) {

        return Proxy.newProxyInstance(

                target.getClass().getClassLoader(),

                interfaces,

                new HelloWorldProxy((HelloWorld) target)

        );

    }

}

 

 

在上述示例中,我们定义了一个原始对象  HelloWorldImpl ,它实现了  HelloWorld  接口。然后,我们创建了一个  HelloWorldProxy  类,它实现了  InvocationHandler  接口,用于处理代理对象的方法调用。在  invoke()  方法中,我们可以在调用原始对象的方法前后执行自定义的逻辑,如打印日志信息。

 

在  main()  方法中,我们创建了一个原始对象  helloWorldImpl ,并使用  createProxy()  方法创建了一个代理对象  helloWorldProxy 。最后,我们使用代理对象执行  sayHello()  方法,并观察控制台输出的日志信息。

 

请注意,使用动态代理需要导入  java.lang.reflect.Proxy  类。

 

总结

我们来总结一下今天学习的内容:

一、代理模式的原理:

代理模式是一种设计模式,它提供了一种通过引入一个代理对象来控制对原始对象的访问的方式。

二、静态代理与动态代理的区别:

静态代理是在编译时创建的代理类,它通过继承原始对象的类或实现其接口,并在其中重写需要代理的方法来实现。

动态代理是在运行时动态创建的代理类,它通过使用反射机制在运行时生成代理对象的字节码,并将其加载到 JVM 中。

三、使用场景

1、远程调用;

2、缓存;

3、记录日志;

4、事务管理;

5、权限检查;

 

希望这个示例能帮助你理解代理模式的原理和使用场景。如果你有任何其他问题,请随时提问。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【十一】MyBatis Plus 原理分析

MyBatis Plus 原理分析 摘要 Java EE开发中必不可少ORM框架&#xff0c;目前行业里最流行的orm框架非Mybatis莫属了&#xff0c;而Mybatis框架本身没有提供api实现&#xff0c;所以市面上推出了Mybatis plus系列框架&#xff0c;plus版是mybatis增强工具&#xff0c;用于简化My…

量子飞跃:从根本上改变复杂问题的解决方式

内容来源&#xff1a;量子前哨&#xff08;ID&#xff1a;Qforepost&#xff09; 编辑丨王珩 编译/排版丨沛贤 深度好文&#xff1a;1000字丨5分钟阅读 利用多功能量子比特的量子计算机已处于解决复杂优化问题的最前沿&#xff0c;例如旅行商问题&#xff0c;这是一个典型的…

虚良SEOPython脚本寄生虫程序源码

本程序&#xff0c;快速收录百度首页&#xff0c;3-5天就可以有流量&#xff0c;长期稳定&#xff0c;可以设置自动推送。 点这里 Python脚本寄生虫程序源码&#xff08;寄生虫电影脚本&#xff09; - 虚良SEO 模板可以自己修改&#xff0c;源码带模板标签说明&#xff0c;简…

AI大模型日报#0415:贾佳亚团队新作王炸、马斯克首款多模态大模型、ChatGPT to B

导读&#xff1a; 欢迎阅读《AI大模型日报》&#xff0c;内容基于Python爬虫和LLM自动生成。目前采用“文心一言”生成了每条资讯的摘要。标题: 融合ChatGPTDALLE3&#xff0c;贾佳亚团队新作开源&#xff1a;识图推理生图一站解决 摘要: 贾佳亚团队推出了多模态模型Mini-Gem…

day58 回文子串 最长回文子序列

题目1&#xff1a;647 回文子串 题目链接&#xff1a;647 回文子串 题意 统计字符串s中回文子串的数目 回文子串是正着读和倒过来读一样的字符串 子串是连续字符组成的一个序列 动态规划 动规五部曲 1&#xff09;dp数组及下标i的含义 dp[i][j] 表示 [s[i]&#xf…

转移插槽简介

4.3.4.转移插槽 我们要将num存储到7004节点&#xff0c;因此需要先看看num的插槽是多少&#xff1a; 如上图所示&#xff0c;num的插槽为2765. 我们可以将0~3000的插槽从7001转移到7004&#xff0c;命令格式如下&#xff1a; 具体命令如下&#xff1a; 建立连接&#xff1a;…

【读书笔记】自动驾驶与机器人中的SLAM技术——高翔

文章会对本书第五章节及以后章节进行总结概括。每日更新一部分。一起读书吧。 第五章——基础点云处理 重点&#xff1a;点云的相邻关系是许多算法的基础 5.1 激光雷达传感器与点云的数学模型 5.1.1激光雷达传感器的数学模型 雷达有两种&#xff1a;机械旋转式激光雷达&…

RocketMQ集群配置

我们集群部署采取采用2m-2s&#xff08;同步双写&#xff09;方式&#xff0c;每个Master配置一个Slave&#xff0c;有多对Master-Slave&#xff0c;HA采用同步双写方式&#xff0c;即只有主备都写成功&#xff0c;才向应用返回成功. 1、服务器环境 序号IP角色架构模式1192.16…

一文详解MES、ERP、SCM、WMS、APS、SCADA、PLM、QMS、CRM、EAM及其关系

经常遇到很多系统&#xff0c;比如&#xff1a;MES、ERP、SCM、WMS、APS、SCADA、PLM、QMS、CRM、EAM&#xff0c;这些都是什么系统&#xff1f;有什么功能和作用&#xff1f;它们之间的关系是怎样的&#xff1f; 今天就一文详细分享给大家。 10大系统之间的关系 ERP 和其他…

深度学习之PyTorch实现卷积神经网络(CNN)

在深度学习领域&#xff0c;卷积神经网络&#xff08;Convolutional Neural Networks&#xff0c;CNN&#xff09;是一种非常强大的模型&#xff0c;专门用于处理图像数据。CNN通过卷积操作和池化操作来提取图像中的特征&#xff0c;具有较好的特征学习能力&#xff0c;特别适用…

机器学习算法快速入门

文章目录 0.简介1.常用术语1) 模型2) 数据集3) 样本&特征4) 向量5) 矩阵6)假设函数&损失函数7&#xff09;拟合&过拟合&欠拟合 2.线性回归3.梯度下降求极值4.Logistic回归算法&#xff08;分类问题&#xff09;5.KNN最邻近分类算法6.朴素贝叶斯分类算法7.决策树…

Python调用微信OCR识别文字和坐标

原理 在看雪看到一篇文章&#xff1a;逆向调用QQ截图NT与WeChatOCR-软件逆向。里面说了怎么调用微信和QQ本地的OCR模型&#xff0c;还有很详细的分析过程。 我稍微看了下文章&#xff0c;多的也看不懂。大概流程是使用mmmojo.dll这个dll来与WeChatOCR.exe做通信的&#xff0c…

1688拍立淘接口:图像识别技术引领电商搜索新革命,打造智能购物新体验!

1688拍立淘接口&#xff1a;技术解析与应用实践 一、引言 在电子商务蓬勃发展的今天&#xff0c;图像识别技术正逐渐成为各大电商平台提升用户体验、优化搜索效率的关键技术之一。作为阿里巴巴旗下的B2B采购批发平台&#xff0c;1688也紧跟技术潮流&#xff0c;推出了拍立淘接…

Dos命令的基础

雷迪斯and the乡亲们 欢迎你们来到 奇幻的编程世界 一、DOS命令基础 提示符 根目录&#xff1a;进入大到分区后&#xff0c;最外层的目录就是跟目录 工作目录&#xff1a;当前的所在位置/所在文件夹 二、cd命令 切换工作目录&#xff1a; cd 格式&#xff1a; cd 目标 …

巧避海森堡不确定性原理!量子比特读出技术重磅突破

内容来源&#xff1a;量子前哨&#xff08;ID&#xff1a;Qforepost&#xff09; 文丨浪味仙 排版丨沛贤 深度好文&#xff1a;1200字丨7分钟阅读 摘要&#xff1a;阿尔托大学研究人员用微测辐射热计替代传统参数放大器&#xff0c;以更少的附加噪声实现非侵入式量子比特测量…

排序链表 - LeetCode 热题 33

大家好&#xff01;我是曾续缘&#x1f639; 今天是《LeetCode 热题 100》系列 发车第 33 天 链表第 12 题 ❤️点赞 &#x1f44d; 收藏 ⭐再看&#xff0c;养成习惯 排序链表 给你链表的头结点 head &#xff0c;请将其按 升序 排列并返回 排序后的链表 。 示例 1&#xff1a…

带你追踪 ICASSP 2024会议现场 韩国夜景令人陶醉

会议之眼 快讯 昨天&#xff0c;2024年的ICASSP&#xff08;International Conference on Acoustics, Speech, and Signal Processing&#xff09;即国际声学、语音和信号处理会议已经在韩国首尔拉开帷幕&#xff01;吸引了众多热情的与会者&#xff01;本届ICASSP会议举办日期…

实验笔记之——RGBD GS-ICP SLAM配置与测试

《RGBD GS-ICP SLAM》是最新开源的一个3DGS-SLAM工作&#xff0c;通过利用GICP来实现当前帧gaussian与已mapping的gaussian进行匹配进行位姿的估算&#xff0c;并通过关键帧的选择策略来进一步提升performance~ Use G-ICP to align the current frame with the 3D GS map whic…

Redis消息队列-基于PubSub的消息队列

7.3 Redis消息队列-基于PubSub的消息队列 PubSub&#xff08;发布订阅&#xff09;是Redis2.0版本引入的消息传递模型。顾名思义&#xff0c;消费者可以订阅一个或多个channel&#xff0c;生产者向对应channel发送消息后&#xff0c;所有订阅者都能收到相关消息。 SUBSCRIBE …

OpenHarmony实战开发-图片选择和下载保存案例。

介绍 本示例介绍图片相关场景的使用&#xff1a;包含访问手机相册图片、选择预览图片并显示选择的图片到当前页面&#xff0c;下载并保存网络图片到手机相册或到指定用户目录两个场景。 效果图预览 使用说明 从主页通用场景集里选择图片选择和下载保存进入首页。分两个场景点…