BeanUtilsVo.copyProperties源码分析
昨天随便说一下pojo和vo和dto的关系给大家2个需求 昨天的博客的地址 https://mp.weixin.qq.com/s?__biz=MzA4MTAwMzA1Mw==&mid=2247484844&idx=1&sn=b950db1607efa078ccc41af61d885dc4&chksm=9f9ad2eea8ed5bf800d2a6d56eddebb33487f1db0741b6a71c0ea262db79480f7fbcb8119ebb&token=722122288&lang=zh_CN#rd 需求
假设是从A复制到B: 需求1:如果B中某字段有值(不为null),则该字段不复制;也就是B中该字段没值时,才进行复制,适合于对B进行补充值的情况。 需求2:如果A中某字段没值(为null),则该字段不复制也就是不要把null复制到B当中
先解决第一个需求
求1:如果B中某字段有值(不为null),则该字段不复制; 也就是B中该字段没值时,才进行复制,适合于对B进行补充值的情况。
解决方案
这里我使用的是自定义注解当自定义注解放在那个字段上面就不进行复制 重写这个复制的源码
@Retention(RetentionPolicy.RUNTIME)@Target({ElementType.FIELD})//// 1.CONSTRUCTOR:用于描述构造器//2.FIELD:用于描述域//3.LOCAL_VARIABLE:用于描述局部变量//4.METHOD:用于描述方法//// 6.PARAMETER:用于描述参数//7.TYPE:用于描述类、接口(包括注解类型) 或enum声明//ElementType.FIELD 只能用在字段上@Documented@Componentpublic @interface judge {}
B
@Data
public class Department implements Serializable { private Integer departmentid; @judge String departmentname; private Integer managerid; private String hh;}
A
@Data
@NoArgsConstructorpublic class DepartmentidDto { private Integer departmentid; private String departmentname; private String hh;
}
main
public class YY { public static void main(String[] args) throws InvocationTargetException, IllegalAccessException { DepartmentidDto department=new DepartmentidDto(); department.setDepartmentid(1); department.setHh("4444444"); department.setDepartmentname("2222222222222"); Department departmentid=new Department(); // departmentid.setDepartmentname("3333333333333333333"); departmentid.setHh("12314");
// 前面是dto a 后面是pojo b BeanUtilsVo.copyProperties(department,departmentid); System.out.println(departmentid.toString());
}}
可以看到a向b复制 字段departmentname的值在b是3333333333333333333 a的值是2222222在b上加上自定义注解
重写方法
public abstract class BeanUtilsVo { /**使用的方法为copyProperties(Object source, Object target)**/ public static void copyProperties(Object source, Object target) throws BeansException { //复制的 被复制的 copyProperties(source, target, (Class)null, (String[])null); } private static void copyProperties(Object source, Object target, @Nullable Class<?> editable, @Nullable String... ignoreProperties) throws BeansException { Assert.notNull(source, "Source must not be null"); /** //对象为空则抛出异常IllegalArgumentException public static void notNull(@Nullable Object object, String message) { if (object == null) { throw new IllegalArgumentException(message); } } **/ Assert.notNull(target, "Target must not be null");
Class<?> actualEditable = target.getClass(); if (editable != null) { if (!editable.isInstance(target)) { throw new IllegalArgumentException("Target class [" + target.getClass().getName() + "] not assignable to Editable class [" + editable.getName() + "]"); }
actualEditable = editable; } //获取PropertyDescriptor(属性描述器)数组,getPropertyDescriptors具体内容看下方 PropertyDescriptor[] targetPds = getPropertyDescriptors(actualEditable); List<String> ignoreList = ignoreProperties != null ? Arrays.asList(ignoreProperties) : null; PropertyDescriptor[] var7 = targetPds; int var8 = targetPds.length;
for(int var9 = 0; var9 < var8; ++var9) { PropertyDescriptor targetPd = var7[var9]; //getWriteMethod中注释说明 //May return null if the property can't be written. //也就是说对应的类中必须有set(写入)方法,否则返回空 Method writeMethod = targetPd.getWriteMethod();
System.out.println("======================="); if (writeMethod != null && (ignoreList == null || !ignoreList.contains(targetPd.getName()))) { //取出对应的属性并读取值 System.out.println( targetPd.getName());// source.getClass().getDeclaredFields(); PropertyDescriptor sourcePd = getPropertyDescriptor(source.getClass(), targetPd.getName());// System.out.println(sourcePd.getClass().getDeclaredFields().toString());// boolean f=false;// if (!Objects.isNull(sourcePd)){// Field[] declaredFields = sourcePd.getClass().getDeclaredFields();// System.out.println("ppppppppppppppppp"+declaredFields.length);// if (declaredFields.length>0){// for (Field declaredField : declaredFields) {// judge fieldAnnotation =declaredField.getDeclaredAnnotation(judge.class);// if (fieldAnnotation!=null){// f=true;// System.out.println("1111111111111");// }// }// }// } if (sourcePd != null) { Method readMethod = sourcePd.getReadMethod(); if (readMethod != null && ClassUtils.isAssignable(writeMethod.getParameterTypes()[0], readMethod.getReturnType())) { try { if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) { readMethod.setAccessible(true); }
Object value = readMethod.invoke(source);// Field[] declaredFields = source.getClass().getDeclaredFields();
System.out.println(value); if (!Objects.isNull(value)){ if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) { writeMethod.setAccessible(true); } Field[] declaredFields = target.getClass().getDeclaredFields(); int i=0; for (Field declaredField : declaredFields) { judge fieldAnnotation =declaredField.getDeclaredAnnotation(judge.class); if (fieldAnnotation!=null){ if (targetPd.getName().equals(declaredField.getName())){ i++; }// System.out.println(declaredField.getName()); }
} if (i==0){ //写入对应的值到目标类 关键 writeMethod.invoke(target, value); } }// if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {// writeMethod.setAccessible(true);// }// Field[] declaredFields = target.getClass().getDeclaredFields();// int i=0;// for (Field declaredField : declaredFields) {// judge fieldAnnotation =declaredField.getDeclaredAnnotation(judge.class);// if (fieldAnnotation!=null){// if (targetPd.getName().equals(declaredField.getName())){// i++;// } System.out.println(declaredField.getName());// }//// }// if (i==0){// //写入对应的值到目标类 关键// writeMethod.invoke(target, value);// } //写入对应的值到目标类 关键// writeMethod.invoke(target, value); } catch (Throwable var15) { throw new FatalBeanException("Could not copy property '" + targetPd.getName() + "' from source to target", var15); } } } } }
}
}
核心是
Field[] declaredFields = target.getClass().getDeclaredFields(); int i=0; for (Field declaredField : declaredFields) { judge fieldAnnotation =declaredField.getDeclaredAnnotation(judge.class); if (fieldAnnotation!=null){ if (targetPd.getName().equals(declaredField.getName())){ i++; }// System.out.println(declaredField.getName()); }
} if (i==0){ //写入对应的值到目标类 关键 writeMethod.invoke(target, value); }
执行看效果
看到里面的值还是没有改变 解决
需求2:如果A中某字段没值(为null),则该字段不复制 也就是不要把null复制到B当中
上面还是可以用
核心
Object value = readMethod.invoke(source);// Field[] declaredFields = source.getClass().getDeclaredFields();
System.out.println(value);
看结果
![](https://files.mdnice.com/user/16658/8f900d9f-0051-4d78-8177-bdae4ef061f3.png)
看到
public class YY { public static void main(String[] args) throws InvocationTargetException, IllegalAccessException { DepartmentidDto department=new DepartmentidDto(); department.setDepartmentid(1);
department.setDepartmentname("2222222222222"); Department departmentid=new Department(); // departmentid.setDepartmentname("3333333333333333333"); departmentid.setHh("12314");
// 前面是dto a 后面是pojo b BeanUtilsVo.copyProperties(department,departmentid); System.out.println(departmentid.toString());
}}
日志
==============================================departmentid1=======================departmentname2222222222222=======================hhnull=======================manageridDepartment(departmentid=1, departmentname=3333333333333333333, managerid=null, hh=12314)
希望可以给大家带来看源码的能力,和学习这个方法的源码是干什么的,怎么进行根据需求去改造这个源码,谢谢你的支持,这个问题,百度上也有,但是写的,看不懂,这个写的比较简单,希望给你带来学习的意义,去理解复制的原理
对这个需求有问题可以加我微信
BeanUtilsVo.copyProperties源码分析相关推荐
- dynamic-datasource-spring-boot-starter源码分析
目录 一.简介 二.源码分析 2.1 整体结构 2.2 自动配置怎么实现的 2.3 如何集成众多连接池 2.4 DS注解如何被拦截处理的 2.5 多数据源动态切换及如何管理多数据源 2.6 组数据源的 ...
- 【Golang源码分析】Go Web常用程序包gorilla/mux的使用与源码简析
目录[阅读时间:约10分钟] 一.概述 二.对比: gorilla/mux与net/http DefaultServeMux 三.简单使用 四.源码简析 1.NewRouter函数 2.HandleF ...
- SpringBoot-web开发(四): SpringMVC的拓展、接管(源码分析)
[SpringBoot-web系列]前文: SpringBoot-web开发(一): 静态资源的导入(源码分析) SpringBoot-web开发(二): 页面和图标定制(源码分析) SpringBo ...
- SpringBoot-web开发(二): 页面和图标定制(源码分析)
[SpringBoot-web系列]前文: SpringBoot-web开发(一): 静态资源的导入(源码分析) 目录 一.首页 1. 源码分析 2. 访问首页测试 二.动态页面 1. 动态资源目录t ...
- SpringBoot-web开发(一): 静态资源的导入(源码分析)
目录 方式一:通过WebJars 1. 什么是webjars? 2. webjars的使用 3. webjars结构 4. 解析源码 5. 测试访问 方式二:放入静态资源目录 1. 源码分析 2. 测 ...
- Yolov3Yolov4网络结构与源码分析
Yolov3&Yolov4网络结构与源码分析 从2018年Yolov3年提出的两年后,在原作者声名放弃更新Yolo算法后,俄罗斯的Alexey大神扛起了Yolov4的大旗. 文章目录 论文汇总 ...
- ViewGroup的Touch事件分发(源码分析)
Android中Touch事件的分发又分为View和ViewGroup的事件分发,View的touch事件分发相对比较简单,可参考 View的Touch事件分发(一.初步了解) View的Touch事 ...
- View的Touch事件分发(二.源码分析)
Android中Touch事件的分发又分为View和ViewGroup的事件分发,先来看简单的View的touch事件分发. 主要分析View的dispatchTouchEvent()方法和onTou ...
- MyBatis原理分析之四:一次SQL查询的源码分析
上回我们讲到Mybatis加载相关的配置文件进行初始化,这回我们讲一下一次SQL查询怎么进行的. 准备工作 Mybatis完成一次SQL查询需要使用的代码如下: Java代码 String res ...
最新文章
- 2018-2019-1 20165212 实验五 通讯协议设计
- python中readlines,在Python中连续两次使用readlines
- CodeForces - 894E Ralph and Mushrooms (强连通缩点+dp)
- JEECG Framework 3.5.2 (快速开发平台) ACE版本发布
- java面试题——java基础(四),java初级面试笔试题
- VisualStudio2019 DLL生成并使用教程(C++)最详细Demo教程
- 让我们一起Go(二)
- 针对piix4_smbus ****host smbus controller not enabled的解决方法
- go tcp socket
- 【Dart语言第1篇】基础学习
- 计算机函数的应用知识点总结,计算机应用 常用函数的使用 常用函数的使用.pptx...
- 快点射!(Swift Injection) 不带这样的!
- 申请美国大学计算机专业,美国TOP20大学计算机专业申请建议
- AT89C51(Atmel)芯片制作简易的频率计
- chkdsk f: /f windows磁盘检查
- 猿辅导9-12编程题3道
- 卫星过顶计算matlab,基于SGP4模型的卫星轨道计算.docx
- 手把手教你实战开发黑白棋实时对战游戏
- 《RFID技术与应用》测试选择题
- MATLAB产生数字调制基带信号(python对比)
热门文章
- 肖特基二极管焊接注意事项和判断正负极的方法
- 从零实践强化学习之连续动作空间上求解RL(PARL)
- word行距设置教程
- 我国大陆运营商的手机号码标准格式为:国家码+手机号码,例如:8613912345678。特点如下: 1、 长度13位; 2、 以86的国家码打头; 3、 手机号码的每一位都是数字。
- android edittext 输入手机号码格式变化
- c语言求最小公倍数和最大公约数
- 直播搭建软件开发直播搭建技术流程解决方案
- android触屏对焦,Android相机对焦模式
- 五种方法教你永久关闭win10自动更新
- 四川大学计算机系统 赵树龙,王俊峰