修改对象的行为和值(代理)

文章目录

  • 前言
  • 一、复制一个对象
  • 二、代理对象
      • 重点来了
  • 总结


前言

最近遇到一个需求,需要在某个位置,统一处理对象的一些属性值:
方案有两种:

  1. 直接复制一份,将属性覆盖后,返回一个新对象
  2. 搞一个代理类,代理这个对象,修改对象的原有行为和值,从而达到修改属性值的目的

一、复制一个对象

这里有现成的hutool 方法,当然不用自己造轮子了,废话不多说,直接上代码:

这里有个类,我设置了id为12 ,我想将id属性值修改为2

public class MainTet {public static void main(String[] args) {Menu menu = new Menu();menu.setMenuCode("12");menu.setId(12);Map<String, Object> overrideProps = new HashMap<>();overrideProps.put("id", 2);Menu menu1 = overrideField(menu,overrideProps);System.out.println(JSONUtil.toJsonStr(menu1));System.out.println(JSONUtil.toJsonStr(menu));}private static <T> T overrideField(T menu,Map<String, Object> overrideProps) {Object object = BeanUtil.copyProperties(menu, menu.getClass());for (Map.Entry<String, Object> entry : overrideProps.entrySet()) {BeanUtil.setFieldValue(object, entry.getKey(), entry.getValue());}return (T) object;}
}

新建一个类的结果
可以看到,返回了新对象,然后值已经被修改,原值仍然是12;

二、代理对象

这个就不一般了,它不是新建了对象,而是创建了一个代理类,类似于spring中的代理对象,然后它不修改之前对象的属性,而是增强
大致思路:

  1. 创建代理对象
  2. 拦截方法,拦截后执行代理方法,而非原方法
public class MainTet {public static void main(String[] args) {Menu menu = new Menu();menu.setMenuCode("12");menu.setId(12);Map<String, Object> overrideProps = new HashMap<>();overrideProps.put("id", 2);Menu proxy = getProxy(menu,overrideProps);System.out.println(proxy.getId());}private static <T> T getProxy(T menu, Map<String, Object> overrideProps) {// 创建代理对象ProxyFactory proxyFactory = new ProxyFactory(menu);proxyFactory.setProxyTargetClass(Boolean.TRUE);Map<String, Object> overrideMap = new HashMap<>();// 设置代理对象的代理方法// 例如 key为id 那么 overrideMap 中的key为getId 和 isidoverrideProps.forEach((k, v) -> {String methodName = "get" + k.substring(0, 1).toUpperCase() + k.substring(1);overrideMap.put(methodName, v);methodName = "is" + k.substring(0, 1).toUpperCase() + k.substring(1);overrideMap.put(methodName, v);});// 利用方法拦截器拦截调用方法,执行代理方法proxyFactory.addAdvice(new MethodInterceptor() {@Overridepublic Object invoke(MethodInvocation invocation) throws Throwable {String methodName = invocation.getMethod().getName();if (overrideMap.containsKey(methodName)) {// 直接返回覆盖值,不执行原方法return overrideMap.get(methodName);}// 执行原方法return invocation.proceed();}});return (T) proxyFactory.getProxy();}
}

打印结果

也被更为了2

重点来了

  • 我在Menu对的getId() 方法中打了断点,但是debug运行过程中,并不会到此处断点
    方法断点

因为,代理后,根本不会执行真正的getId 方法,而是在 MethodInterceptor的 invoke 中,根据判断,直接返回覆盖值


总结

第二种方式比较高大上,相当于手动创建了代理对象,并修改了对象的原有属性和行为!

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

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

相关文章

【GoLang入门教程】Go语言几种标准库介绍(四)

编程语言的未来&#xff1f; 文章目录 编程语言的未来&#xff1f;前言几种库fmt库 (格式化操作)关键函数&#xff1a;示例 Go库标准库第三方库示例 html库(HTML 转义及模板系统)主要功能&#xff1a;示例 总结专栏集锦写在最后 前言 上一篇&#xff0c;我们介绍了debug、enco…

关于“Python”的核心知识点整理大全65

目录 20.2.19 设置 SECRET_KEY 20.2.20 将项目从 Heroku 删除 注意 20.3 小结 附录 A 安装Python A.1.1 确定已安装的版本 A.1.2 在 Linux 系统中安装 Python 3 A.2 在 OS X 系统中安装 Python A.2.1 确定已安装的版本 A.2.2 使用 Homebrew 来安装 Python 3 注意 …

基于商品列表的拖拽排序后端实现

目录 一&#xff1a;实现思路 二&#xff1a;实现步骤 二&#xff1a;实现代码 三&#xff1a;注意点 一&#xff1a;实现思路 后台实现拖拽排序通常需要与前端进行配合&#xff0c;对商品的列表拖拽排序&#xff0c;前端需要告诉后端拖拽的元素和拖动的位置。 这里我们假…

Matlab三维绘图

绘制三维图plot3 t0:pi/50:10*pi; xsin(t); ycos(t); zt; plot3(x,y,z); 产生栅格数据点meshgrid 这个接口在绘制三维图像里面相当重要&#xff0c;很多时候要将向量变成矩阵才能绘制三维图。 x0:0.5:5; y0:1:10; [X,Y]meshgrid(x,y); plot(X,Y,o); x和y是向量&#xff0c;…

RocketMQ单机部署完整学习笔记

文章目录 前言一、RocketMQ是什么&#xff1f;二、使用步骤1.安装MQ1.安装JDK2.安装mq3.MQ配置(核心) 2.搭建可视化dashboard1.下载源码2.修改配置3.启动 3.整合java1.生产者2.消费者3.启动生产者4.启动消费者5.dashboard添加消费组 三、总结全部的配置 前言 本文是基于4.X版本…

LeetCode 2221. 数组的三角和

文章目录 1. 题目 2. 解题 1. 题目 给你一个下标从 0 开始的整数数组 nums &#xff0c;其中 nums[i] 是 0 到 9 之间&#xff08;两者都包含&#xff09;的一个数字。 nums 的 三角和 是执行以下操作以后最后剩下元素的值&#xff1a; num…

I.MX6ULL开发笔记(二)——硬件外设操作

0x01 点亮第一个RGB灯 在文章http://t.csdnimg.cn/EGWt9中有介绍Linux下文件目录&#xff0c;那么在Linux系统下&#xff0c;RGB灯也是一个设备&#xff0c;所以我们需要到/sys目录下去操作这个设备。 之后&#xff0c;我们进入到class目录&#xff0c;这里挂载着开发板上的外…

Mongodb删除操作中字符序对结果的影响

本文还是要从删除操作的语法说起。 db.collection.deleteMany(<filter>,{writeConcern: <document>,collation: <document>,hint: <document|string>} ) 删除语法中&#xff0c;可以指定数据写入策略&#xff0c;字符序和使用的索引字段。 字符序&a…

MySQL第四战:视图以及常见面试题(上)

目录 目录&#xff1a; 一.视图 1.介绍什么是视图 2.视图的语法 语法讲解 实例操作 二.MySQL面试题 1.SQL脚本 2.面试题实战 三.思维导图 目录&#xff1a; 随着数字化时代的飞速发展&#xff0c;数据库技术&#xff0c;特别是MySQL&#xff0c;已经成为IT领域中不可…

Mybatis简易搭建并查询数据库表内所有数据

搭建步骤 1.在mysql中创建user表&#xff0c;添加数据2.创建maven模块&#xff0c;导入坐标3.在资源文件夹中导入需要用到的logback.xml4.编写MyBatis 核心配置文件->替换连接信息 解决硬编码问题5.编写 SQL映射文件->统一管理sgl语句&#xff0c;解决硬编码问题6.编码定…

HackTheBox - Medium - Linux - Ambassador

Ambassador Ambassador 是一台中等难度的 Linux 机器&#xff0c;用于解决硬编码的明文凭据留在旧版本代码中的问题。首先&#xff0c;“Grafana”CVE &#xff08;“CVE-2021-43798”&#xff09; 用于读取目标上的任意文件。在研究了服务的常见配置方式后&#xff0c;将在其…

【管理篇 / 登录】❀ 06. macOS下使用USB配置线登录 ❀ FortiGate 防火墙

【简介】飞塔防火墙上都会配有CONSOLE接口&#xff0c;包装里都会配置一根USB配置线&#xff0c;通过这个接口和这根线&#xff0c;我们可以用命令的方式登录飞塔防火墙。随着苹果电脑的普及&#xff0c;我们来学习如何在macOS中使用USB配置线登录飞塔防火墙。 早期飞塔防火墙包…