使用BeanCopier复制对象属性值,遇到NullPointerException?

文章目录

一、场景

项目中,为了数据安全,由于身份证属于敏感信息,需要加密后返回给页面解密显示,但DTO中出现了一种骚操作,身份证的get方法,把身份证转成大写的了,当我们通过BeanUtils.copyProperties复制属性值给VO对象,就会调用get方法获取值,然后赋值,所以我们的加密内容会被转为大写,导致页面无法解密,最终我们额外写了一个getIdentityCardTemp()方法,先设到临时变量,再进行BeanUtils.copyProperties,最后把临时变量值赋给identityCard。

代码如下:

java 复制代码
private String identityCard;
public String getIdentityCard() {
	return identityCard.toUpperCase();
}
public void setIdentityCard(String identityCard) {
	this.identityCard= identityCard;
}
public String getIdentityCardTemp() {
	return identityCard;
}

二、问题

代码按照上面那样写法,就会出现NPE

java 复制代码
java.lang.NullPointerException
	at net.sf.cglib.core.ReflectUtils.getMethodInfo(ReflectUtils.java:424)
	at net.sf.cglib.beans.BeanCopier$Generator.generateClass(BeanCopier.java:133)
	at net.sf.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
	at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:216)
	at net.sf.cglib.beans.BeanCopier$Generator.create(BeanCopier.java:90)
	at net.sf.cglib.beans.BeanCopier.create(BeanCopier.java:50)
	at com.msedu.common.utils.BeanUtils.copyProperties(BeanUtils.java:74)
	at com.msedu.common.utils.BeanUtils.copyListProperties(BeanUtils.java:53)

三、分析

BeanUtils.copyProperties,在项目中其实就是使用BeanCopier用于复制对象属性值,具体原理如下:

  • 在第一次使用BeanCopier复制对象属性值时,会通过反射获取源对象和目标对象的Class对象。
  • 根据源对象和目标对象的Class对象,生成一个Key对象,用于缓存复制过程中生成的转换器。
  • 通过Key对象从缓存中获取转换器,如果缓存中不存在,则创建一个新的转换器。
  • 转换器会通过反射获取源对象和目标对象的属性列表,并逐个复制属性值。
  • 复制属性值时,转换器会根据属性的类型和名称,使用反射获取属性的getter和setter方法,并通过调用这些方法来实现属性值的复制。

总的来说,就是赋值的时候,需要获取属性值的get和set方法,再来分析下报错信息,找到具体的报错源码,如下:

其实就是获取不到我们属性的set方法报错了,但我们都没有声明identityCardTemp属性,而是声明了getIdentityCardTemp方法,为什么需要set方法呢?
关键在于PropertyDescriptor[] setters = ReflectUtils.getBeanGetters(target);里面的逻辑实现,大概就是通过get方法获取对应的set方法,而不是通过属性值,所以到这里就明白原因了

四、解决

声明一个对应的set方法即可

java 复制代码
public String getIdentityCardTemp() {
	return identityCard;
}
public void setIdentityCardTemp(String identityCard) {
	this.identityCard= identityCard;
}

五、总结

在使用BeanCopier复制对象属性的时候,是需要你在实体类中同时有set和get方法的,就算你不需要赋值,实体类中声明了get方法的话,对应的set不要省,不然就会报NullPointerException

相关推荐
qq_297574672 分钟前
SpringBoot项目长时间未访问,Tomcat临时文件夹被删除?解决方案来了
spring boot·后端·tomcat
摇滚侠7 分钟前
macbook shell 客户端推荐 Electerm macbook 版本下载链接
java·开发语言
一个有梦有戏的人8 分钟前
Python3基础:函数基础,解锁模块化编程新技能
后端·python
程序员布吉岛9 分钟前
Java 后端定时任务怎么选:@Scheduled、Quartz 还是 XXL-Job?(对比 + 避坑 + 选型)
java·开发语言
知无不研13 分钟前
lambda表达式的原理和由来
java·开发语言·c++·lambda表达式
逍遥德14 分钟前
Sring事务详解之02.如何使用编程式事务?
java·服务器·数据库·后端·sql·spring
笨蛋不要掉眼泪14 分钟前
Redis哨兵机制全解析:原理、配置与实战故障转移演示
java·数据库·redis·缓存·bootstrap
Coder_Boy_29 分钟前
基于SpringAI的在线考试系统-整体架构优化设计方案
java·数据库·人工智能·spring boot·架构·ddd
草履虫建模7 小时前
力扣算法 1768. 交替合并字符串
java·开发语言·算法·leetcode·职场和发展·idea·基础
qq_297574679 小时前
【实战教程】SpringBoot 实现多文件批量下载并打包为 ZIP 压缩包
java·spring boot·后端