Spring之代理模式

1、概念

1.1 介绍

二十三种设计模式中的一种,属于结构型模式。它的作用就是通过提供一个代理类,让我们在调用目标方法的时候,不再是直接对目标方法进行调用,而是通过代理类间接调用。让不属于目标方法核心逻辑的代码从目标方法中剥离出来——解耦。调用目标方法时先调用代理对象的方法,减少对目标方法的调用和打扰,同时让附加功能能够集中在一起也有利于统一维护。

在这里插入图片描述
使用代理后:
在这里插入图片描述
②生活中的代理

  • 广告商找大明星拍广告需要经过经纪人
  • 合作伙伴找大老板谈合作要约见面时间需要经过秘书
  • 房产中介是买卖双方的代理
1.2 相关术语
  • 代理:将非核心逻辑剥离出来以后,封装这些非核心逻辑的类、对象、方法。
  • 目标:被代理“套用”了非核心逻辑代码的类、对象、方法。

2 静态代理

    public interface Calculator {int add(int i, int j);int sub(int i, int j);int mul(int i, int j);int div(int i, int j);}
    package com.giser.java.spring6.calcu.impl;import com.giser.java.spring6.calcu.Calculator;/*** @author giserDev* @description 基础实现* @date 2024-01-06 23:41:55*/public class CalculatorImpl implements Calculator {@Overridepublic int add(int i, int j) {int result = i + j;System.out.println("方法内部 result = " + result);return result;}@Overridepublic int sub(int i, int j) {int result = i - j;System.out.println("方法内部 result = " + result);return result;}@Overridepublic int mul(int i, int j) {int result = i * j;System.out.println("方法内部 result = " + result);return result;}@Overridepublic int div(int i, int j) {int result = i / j;System.out.println("方法内部 result = " + result);return result;}}

创建静态代理类

    package com.giser.java.spring6.calcu.impl;import com.giser.java.spring6.calcu.Calculator;/*** @author giserDev* @description* 提出问题** ①现有代码缺陷** 针对带日志功能的实现类,我们发现有如下缺陷:** - 对核心业务功能有干扰,导致程序员在开发核心业务功能时分散了精力* - 附加功能分散在各个业务功能方法中,不利于统一维护** ②解决思路** 解决这两个问题,核心就是:解耦。我们需要把附加功能从业务功能代码中抽取出来。** ③困难** 解决问题的困难:要抽取的代码在方法内部,靠以前把子类中的重复代码抽取到父类的方式没法解决。所以需要引入新的技术。* @date 2024-01-06 23:43:25*/public class CalculatorLogImpl implements Calculator {@Overridepublic int add(int i, int j) {System.out.println("[日志] add 方法开始了,参数是:" + i + "," + j);int result = i + j;System.out.println("方法内部 result = " + result);System.out.println("[日志] add 方法结束了,结果是:" + result);return result;}@Overridepublic int sub(int i, int j) {System.out.println("[日志] sub 方法开始了,参数是:" + i + "," + j);int result = i - j;System.out.println("方法内部 result = " + result);System.out.println("[日志] sub 方法结束了,结果是:" + result);return result;}@Overridepublic int mul(int i, int j) {System.out.println("[日志] mul 方法开始了,参数是:" + i + "," + j);int result = i * j;System.out.println("方法内部 result = " + result);System.out.println("[日志] mul 方法结束了,结果是:" + result);return result;}@Overridepublic int div(int i, int j) {System.out.println("[日志] div 方法开始了,参数是:" + i + "," + j);int result = i / j;System.out.println("方法内部 result = " + result);System.out.println("[日志] div 方法结束了,结果是:" + result);return result;}}

静态代理的问题:

静态代理确实实现了解耦,但是由于代码都写死了,完全不具备任何的灵活性。就拿日志功能来说,将来其他地方也需要附加日志,那还得再声明更多个静态代理类,那就产生了大量重复的代码,日志功能还是分散的,没有统一管理。提出进一步的需求:将日志功能集中到一个代理类中,将来有任何日志需求,都通过这一个代理类来实现。这就需要使用动态代理技术了。

3 动态代理

在这里插入图片描述

package com.giser.spring6.calcu.impl.dynamicproxy;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;/*** @author giserDev* @description 代理工厂类* @date 2024-01-06 23:52:21*/
public class DynamicProxyFactory {/*** 被持有的被代理对象*/private Object target;public DynamicProxyFactory(Object target) {this.target = target;}/*** 创建代理对象* @return 代理对象*/public Object getProxy(){return Proxy.newProxyInstance(// 代理对象的类加载器target.getClass().getClassLoader(),// 代理对象实现的接口列表target.getClass().getInterfaces(),// 处理器new InvocationHandler() {/**** @param proxy the proxy instance that the method was invoked on*              代理对象** @param method the {@code Method} instance corresponding to* the interface method invoked on the proxy instance.  The declaring* class of the {@code Method} object will be the interface that* the method was declared in, which may be a superinterface of the* proxy interface that the proxy class inherits the method through.*               代理对象需要实现的方法** @param args an array of objects containing the values of the* arguments passed in the method invocation on the proxy instance,* or {@code null} if interface method takes no arguments.* Arguments of primitive types are wrapped in instances of the* appropriate primitive wrapper class, such as* {@code java.lang.Integer} or {@code java.lang.Boolean}.*             method对应的方法参数** @return* @throws Throwable*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Object result = null;try {System.out.println("[动态代理][日志] "+method.getName()+",参数:"+ Arrays.toString(args));result = method.invoke(target, args);System.out.println("[动态代理][日志] "+method.getName()+",结果:"+ result);} catch (Exception e) {e.printStackTrace();System.out.println("[动态代理][日志] "+method.getName()+",异常:"+e.getMessage());} finally {System.out.println("[动态代理][日志] "+method.getName()+",方法执行完毕");}return result;}});}}

测试

package com.giser.spring6;import com.giser.spring6.calcu.Calculator;
import com.giser.spring6.calcu.impl.CalculatorImpl;
import com.giser.spring6.calcu.impl.dynamicproxy.DynamicProxyFactory;/*** @author giserDev* @description 动态代理测试* @date 2024-01-07 00:02:54*/
public class DynamicProxyTest {public static void main(String[] args) {DynamicProxyFactory dynamicProxyFactory = new DynamicProxyFactory(new CalculatorImpl());Calculator proxy = (Calculator) dynamicProxyFactory.getProxy();int add = proxy.add(1, 3);}}

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

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

相关文章

Redis 有序集合(sorted set) 命令

目录 1.Redis Zrevrank 命令 - 返回有序集合中指定成员的排名,有序集成员按分数值递减(从大到小)排序简介语法可用版本: > 2.2.0返回值: 如果成员是有序集 key 的成员,返回成员的排名。 如果成员不是有序集 key 的成员,返回 nil 。 示例 2…

2024阿里云优惠_阿里云活动中心

2024年阿里云优惠活动大全,包括阿里云服务器优惠活动清单、配置价格表、域名优惠活动、阿里云建站活动、阿里云优惠代金券免费领取、对象存储OSS活动、企业邮箱优惠、无影云电脑优惠、CDN特惠等等,阿里云百科aliyunbaike.com分享2024阿里云优惠活动大全_…

循环队列的队空队满情况

有题目: 循环队列放在一维数组A[0....M-1]中,end1指向队头元素,end2指向队尾元素的后一个位置。假设队列两端均可进行入队和出队操作,队列中最多能容纳M-1个元素。初始时为空。下列判断队空和队满的条件中,正确的是 …

用可视化案例讲Rust编程1. 怎么能学会Rust

用可视化案例讲Rust编程 1. 怎么能学会Rust 如果要列举Rust的优势,恐怕写个十条八条是写不完的,而且不管写哪条优势,都有很多同学跳起来反驳,比如我们说Rust比C/C内存安全,肯定有同学说C 20也支持内存安全&#xff0…

Java数组:一维数组、二维数组、Arrays

文章目录 1、一维数组1.1 数组概念1.2 数组的声明1.3 数组的静态初始化1.4 数组的动态初始化1.5 地址值1.6 数组元素访问1.7 索引1.8 数组的遍历1.9 数组两种初始化方式的区别 2、二维数组2.1 二维数组的声明2.2 二维数组的静态初始化2.3 二维数组的动态初始化2.4 二维数组的遍…

LCD—液晶显示

本节主要介绍以下内容 显示器简介 液晶控制原理 秉火3.2寸液晶屏简介 使用FSMC模拟8080时序 NOR FLASH时序结构体 FSMC初始化结构体 一、显示器简介 显示器属于计算机的I/O设备,即输入输出设备。它是一种将特定电子信息输出到屏幕上再反射到人眼的显示工具。…

计算机毕业设计 基于Javaweb的城乡居民基本医疗信息管理系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍:✌从事软件开发10年之余,专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ 🍅文末获取源码联系🍅 👇🏻 精…

【Linux Shell】2. Shell 变量

文章目录 【 1. 变量命名规则 】【 2. 变量的使用 】【 3. 只读变量 】【 4. 删除变量 】【 5. 变量类型 】【 6. Shell 字符串 】6.1 字符串分类6.2 字符串操作 【 7. Shell 注释 】7.1 单行注释7.2 多行注释 【 1. 变量命名规则 】 定义变量时,变量名不加美元符号…

Linux系统使用超详细(八)~磁盘管理

目录 一、认识磁盘 二、磁盘运行机制 三、磁盘检查 3.1查找设备名称和分区号 3.1.1使用lsblk命令: 3.1.2使用fdisk命令: 3.1.3使用blkid命令: 3.2检查方向 3.2.1文件系统完整性: 3.2.2磁盘健康状态: 3.2.3磁…

2024-python画图永久解决 matplotlib 中文乱码

2024-python画图永久解决 matplotlib 中文乱码 不多说了吧,大家肯定是自己安装了python,这些环境了,毕竟都知道乱码了,所有此处省略1万字,如果这些前期不会的,就不要来找我了,自己解决&#xf…

均匀与准均匀 B样条算法

B 样条曲线的定义 p ( t ) ∑ i 0 n P i F i , k ( t ) p(t) \sum_{i0}{n} P_i F_{i, k}(t) p(t)i0∑​nPi​Fi,k​(t) 方程中 n 1 n1 n1 个控制点, P i P_i Pi​, i 0 , 1 , ⋯ n i0, 1, \cdots n i0,1,⋯n 要用到 n 1 n1 n1 个 k k k 次 B 样条基函数 …

DeepPurpose 生物化学深度学习库;蛋白靶点小分子药物对接亲和力预测虚拟筛选

参考: https://blog.csdn.net/c9Yv2cf9I06K2A9E/article/details/107649770 https://github.com/kexinhuang12345/DeepPurpose ##安装 pip install DeepPurpose rdkitDeepPurpose包括: 数据: 关联TDC库下载,是同一作者开发的 https://blog.csdn.net/weixin_42357472/artic…