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

文章目录

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


前言

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

  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.mzph.cn/news/603273.shtml

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

相关文章

Guava:Throwables 异常工具

Guava Throwables 类 Throwable 类&#xff0c;简化异常和错误的传播与检查 类方法说明 官方文档&#xff1a;Throwables (Guava: Google Core Libraries for Java 27.0.1-jre API) 方法类型方法描述static List<Throwable>getCausalChain(Throwable throwable) 获取…

概率论与数理统计 知识点+课后习题

文章目录 &#x1f496; [学习资源整合](https://www.cnblogs.com/duisheng/p/17872980.html)&#x1f4da; 总复习&#x1f4d9; 选择题&#x1f4d9; 填空题&#x1f4d9; 大题1. 概率2. 概率3. 概率4. P5. 概率6. 概率密度函数 F ( X ) F(X) F(X)7. 分布列求方差 V ( X ) …

[蓝桥杯学习] 树状数组的二分

要解决这个问题&#xff0c;插入和删除可以用STL实现&#xff0c;2操作如果用树状数组实现的话&#xff0c;将数的值作为树状数组的下标&#xff0c;即值域。 树状数组有两种操作&#xff0c;一个是更新某点的值&#xff0c;另一个是求区间和。 mid (lr)/2 &#xff0c;求和 …

spring boot + mysql+ mybatis-plus开箱即用项目

开箱即用后端项目 用于中小型项目快速构建web api&#xff0c;灵活度高&#xff0c;可根据项目自由定制所需的依赖插件&#xff0c;此项目区分了开发、测试、和生产环境 此项目集成了mysql mybatis-plus &#xff0c;使用mybatis-plus的自动填充功能实现通用字段的赋值&#x…

生信 R语言

11.芯片表达矩阵下游分析 ​rm(list ls())#清除所有变量 options(stringsAsFactors F) #BiocManager::install("CLL") suppressPackageStartupMessages(library(CLL)) data("sCLLex") sCLLex ## ExpressionSet (storageMode: lockedEnvironment) ## as…

Nougat:科学文档的OCR 使用记录

https://github.com/facebookresearch/nougat python环境需要在3.8以上 安装&#xff1a;pip install nougat-ocr 模型默认下载地址&#xff1a;/home/****/.cache/torch/hub/nougat-0.1.0-small 环境安装好之后默认使用cpu UserWarning: CUDA initialization: The NVIDIA dr…

LeetCode——队列

队列 主要是优先队列的例题&#xff0c;以及优先队列如何使用&#xff08;堆的性质&#xff0c;队列的存取&#xff09; 优先队列&#xff1a; PriorityQueue<Integer> minHeap new PriorityQueue<>(); minHeap.peek(); // 获取堆顶元素 minHeap.offer(num); …

2024美赛数学建模常用数学建模模型之——层次分析法

一、层次分析法的基本原理与步骤 人们在进行社会的、经济的以及科学管理领域问题的系统分析中&#xff0c;面临的常常是 一个由相互关联、相互制约的众多因素构成的复杂而往往缺少定量数据的系统。层次 分析法为这类问题的决策和排序提供了一种新的、简洁而实用的建模方法。 …

Kafka(七)可靠性

目录 1 可靠的数据传递1.1 Kafka的可靠性保证1.2 复制1.3 Broker配置1.3.1 复制系数1.3.2 broker的位置分布1.3.3 不彻底的首领选举1.3.4 最少同步副本1.3.5 保持副本同步1.3.6 持久化到磁盘 1.2 在可靠的系统中使用生产者1.2.1 根据需求配置恰当的acks1.2.2 配置重试参数1.2.3…

视频智能分析支持摄像头异常位移检测,监测摄像机异常位移变化,保障监控状态

我们经常在生产场景中会遇到摄像头经过风吹日晒&#xff0c;或者异常的触碰&#xff0c;导致了角度或者位置的变化&#xff0c;这种情况下&#xff0c;如果不及时做出调整&#xff0c;会导致原本的监控条件被破坏&#xff0c;发生事件需要追溯的时候&#xff0c;查不到对应位置…

找到字符串中所有字母异位词【滑动窗口】

Problem: 438. 找到字符串中所有字母异位词 文章目录 思路 & 解题方法复杂度Code 思路 & 解题方法 主要需要注意s长度可能比p短 复杂度 时间复杂度: 添加时间复杂度, 示例&#xff1a; O ( 26 n ) O(26n) O(26n) 空间复杂度: 添加空间复杂度, 示例&#xff1a; O ( …

Camtasia2024苹果Mac电脑版(屏幕录制剪辑软件)

Camtasia Mac2024免费版是一款由TechSmith公司官方进行汉化推出的最新版本&#xff0c;借助Camtasia&#xff0c;您可以轻松记录屏幕并创建优美&#xff0c;专业的视频。记录所有内容-您的整个屏幕或只是一个窗口。或者&#xff0c;添加您已经拥有的视频&#xff0c;图像&#…

第十三章 接口测试(笔记)

一、接口测试分类 内部接口&#xff1a;测试被测系统各个子模块之间的接口&#xff0c;或者被测系统提供给内部系统使用的接口 外部接口&#xff1a; 1.被测系统调用外部的接口 2.系统对外提供的接口 接口测试重点&#xff1a;检查接口参数传递的正确性&#xff0c;接口功能的…

java数据结构与算法刷题-----LeetCode303. 区域和检索 - 数组不可变

java数据结构与算法刷题目录&#xff08;剑指Offer、LeetCode、ACM&#xff09;-----主目录-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/123063846 很多人觉得动态规划很难&#xff0c;但它就是固定套路而已。其实动态规划只…

Chunjun纯钧(Flinkx)同步任务开发通用配置参数详解

Chunjun纯钧(Flinkx)是一款稳定、易用、高效、批流一体的数据集成框架,目前基于实时计算引擎Flink实现多种异构数据源之间的数据同步与计算,支持JSON模版配置任务,兼容FlinkSQL语法。本文对chunjun同步任务的配置文件进行详细的介绍和总结。 文章目录 配置文件结构详解Conte…

HackTheBox - Medium - Linux - Ambassador

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

2023「总结」,2024「展望」

前言 时光荏苒&#xff0c;岁月如梭&#xff0c;转眼已经进入2024年了。回想过去的2023年&#xff0c;成长了很多&#xff0c;有收获&#xff0c;有付出&#xff0c;也有一丝丝的遗憾。   其实在写这篇文章之前我思考了很久&#xff0c;一直不知如何下手&#xff0c;也许这是…

el-select显示不全

css代码&#xff1a; .el-select-dropdown__wrap.el-scrollbar__wrap {margin-bottom: 0 !important; }

nodejs 实现内部之间接口的相互调用

ChatGPT4.0国内站点&#xff1a;海鲸AI 在 Node.js 中调用服务内的接口&#xff0c;通常是指发起 HTTP 请求到某个服务的 API 端点。这可以通过 Node.js 的内置 http 模块来实现&#xff0c;或者使用第三方库如 axios、request&#xff08;已被弃用&#xff09;、node-fetch 等…

Redis 常见的几种数据结构说一下?各自的使用场景?

文章目录 Redis 常见的几种数据结构说一下&#xff1f;各自的使用场景&#xff1f;stringlisthashsorted setbitmap使用场景&#xff1a; Redis 常见的几种数据结构说一下&#xff1f;各自的使用场景&#xff1f; string 介绍&#xff1a;string 数据结构是简单的 key-value …