使用BeanCopier抛出NullPointerException溯源

2023-05-16

问题

使用cglib提供的net.sf.cglib.beans.BeanCopier进行对象拷贝时,抛出如下异常:

Exception in thread "main" java.lang.NullPointerException
	at net.sf.cglib.core.ReflectUtils.getMethodInfo(ReflectUtils.java:421)
	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.jd.paytrade.CglibTest.main(CglibTest.java:12)

结论

BeanCopier类在cglib的3.2.0版本前(3.2.0已修复)有BUG,当target类含有没有定义标准set方法的属性时,会抛出上述异常。bug修复commit。在3.2.0版本后,相同情况下不会抛出异常,只不过未定义标准set方法的属性无法被成功赋值。

解决

方案一:升级项目中引入的cglib版本;
方案二:考虑到老项目升级公共组件影响范围过大,老老实实使用set、get进行对象属性拷贝;

背景

引用其他部门的jar包,对其中的类使用BeanCopier赋值,抛出上述异常。发现外部包中的Bean定义都采用了建造者模式,set方法定义类似:

public TargetBean setId(Long id) {
    this.id = id;
    return this;
}

而Cglib提取set方法所使用的Java自省API获取set方法的代码如下(java.beans.Introspector#getTargetPropertyInfo):

static final String SET_PREFIX = "set";
……
} else if (argCount == 1) {  // 参数个数为1个
    if (int.class.equals(argTypes[0]) && name.startsWith(GET_PREFIX)) {
        pd = new IndexedPropertyDescriptor(this.beanClass, name.substring(3), null, null, method, null);
    } else if (void.class.equals(resultType) && name.startsWith(SET_PREFIX)) {  // 返回值为void类型 && set开头
        // Simple setter
        pd = new PropertyDescriptor(this.beanClass, name.substring(3), null, method);
        if (throwsException(method, PropertyVetoException.class)) {
             pd.setConstrained(true);
        }
}

由上述代码可知被识别为set方法需要满足:

  1. 参数个数为1个
  2. 返回值为void类型
  3. set开头

显然用建造者模式定义的Bean不符合第二条,纵使升级了Cglib版本不报错了,值也拷贝不上。而BeanUtils的拷贝性能又不行,只好改为了一个一个属性get、set。

思考

使用BeanCopier或者BeanUtils进行对象拷贝,代码是比较简洁,但一定是好的吗?

个人认为不然,在日常开发中,如果要对某些字段的赋值或使用方式进行改动,首先会想到去看看这个属性在哪里被用到了,查看方法自然是去追踪该属性的set方法与get方法。如果所有的赋值都使用BeanCopier此类工具,则没有对set、get的显示调用,排查赋值路径会很困难。

个人日常开发中只有在明确的参数透传环节并且source和target相似度在百分之九十以上才会使用此类工具,其余情况如不同层级间Bean的赋值,或者取source中部分字段给target,均会使用get、set方法进行赋值,便于后续系统的维护。并且,get、set效率是最高的(狗头)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用BeanCopier抛出NullPointerException溯源 的相关文章

随机推荐

  • Win10下开机自动启动运行bat脚本并打开cmd运行命令

    场景 xff1a 本菜鸟有一台工作站安装了windows10操作系统 xff0c 机器设置的是开机自动启动 xff0c 但是维护人员无法一直在机房 xff0c 一旦机房断电重启就会导致工作站中运行的程序无法重新启动 xff0c 需要维护人员
  • 银河麒麟V10系统 syslog和kern.log文件过大问题解决,定时清理日志文件

    文章目录 1 新建clear log sh脚本文件 2 设置cron任务 3 解决不执行的方法 需求 在使用银河麒麟V10系统时 var log kern log 和 var log syslog两个文件随着使用的时间增长会一直增大 最后可
  • 2.龙芯2k1000 linux3.10内核编译过程

    龙芯2k1000 linux3 10内核编译过程 文章目录 龙芯2k1000 linux3 10内核编译过程 xff08 一 xff09 在Ubuntu环境下载并配置交叉编译链 xff08 二 xff09 下载linux3 10内核源码 x
  • Vulkan实战之逻辑设备和队列

    文章目录 介绍指定要创建的队列指定使用的设备特性创建逻辑设备检索队列句柄最终代码 介绍 在选择要使用的物理设备之后 xff0c 我们需要设置一个逻辑设备来与它接口 逻辑设备创建过程类似于实例创建过程 xff0c 并描述了我们想要使用的特性
  • Vulkan实战之Window surface

    文章目录 创建window surface查询演示支持创建surface队列最终代码 由于Vulkan是一个平台无关的API xff0c 因此它不能自己直接与窗口系统接口交互 为了在Vulkan和窗口系统之间建立连接并将结果显示到屏幕上 x
  • 飞腾UEFI配置GPIO—飞腾FT2000/4 (D2000/8) GPIO引脚配置及使用

    文章目录 一 FT2000 4 GPIO介绍 GPIO 接口信号说明 专用GPIO GPIO0 A1 GPIO0 A7 SCI 介绍 二 UEFI下配置GPIO相关寄存器 GPIO相关相关引脚功能配置说明 UEFI配置GPIO相关代码 UE
  • stm32-sbus数据接收,并通过CAN转发给车辆控制

    1 xff09 串口程序 代码如下 xff1a span class token macro property span class token directive hash span span class token directive
  • 基于stm32的无线多点温度采集系统设计

    本科时候做过关于ds18b20温度传感器的课程设计 xff0c 当时好像是先用单片机A采集温度 xff0c 其中用矩阵键盘设置报警值 xff0c 然后通过232串口将温度值传给单片机B xff0c 单片机B上的数码管显示 xff0c 同时单
  • 无刷电机和桨叶的选择

    无刷电机和桨叶的选择 无刷电机的kv值越高 就要配越小的螺旋桨 简单说 高kv配小桨 低kv配大桨 无刷电机KV值定义为 转速 V xff0c 意思为输入电压增加1伏特 xff0c 无刷电机空转转速增加的转速值 由此无刷电机电压的输入与电机
  • Intel RealSense Win10+QT+Cmaker 开发环境搭建

    文章目录 一 Intel RealSense SDK开发工具下载安装二 QT 43 CMaker配置Intel RealSense SDK2 0开发环境 一 Intel RealSense SDK开发工具下载安装 从官方github上下载S
  • NVIDIA Jetson不同系列对比

    文章目录 一 NVIDIA Jetson介绍二 NVIDIA Jetson模组比较 一 NVIDIA Jetson介绍 NVIDIA Jetson 是世界领先的平台 xff0c 适用于自主机器和其他嵌入式应用程序 该平台包括 Jetson
  • SLAM笔记五——EKF-SLAM

    上一节主要讲解了EKF的基本原理 xff0c 这一次主要关注如何将EKF算法应用在SLAM上 EKF SLAM 现在的问题就是解决下面这个概率分布的估计问题 xff1a 阴影部分为未知 这里我们需要确定均值和方差到底是什么 xff1f 假设
  • HTTP协议-报文解析

    概述 HTTP xff08 超文本传输协议 xff09 是一个基于请求与响应模式的 无状态的 应用层的协议 xff0c 常基于TCP的连接方式 HTTP消息由客户端到服务器的请求和服务器到客户端的响应组成 请求消息和响应消息的组成 xff1
  • 站在巨人的肩膀上——Linux信号量操作

    感谢那些让我度过此学海的无名勇士 信号量简介 xff1a 在对于临界区资源管理的过程中 xff0c 多个程序同时访问一个共享资源经常容易引发一系列问题 xff1a 如死锁 xff0c 结果不唯一等等 xff0c 在1965年 xff0c 由
  • 详解常用的ROS内置消息类型

    1 std msgs 该类型是ROS内置的标准消息类型 xff0c 是最基础的消息类型 xff08 1 xff09 对于单类型 xff0c 下表是其与C 43 43 和python的对应关系 xff1a Primitive TypeSeri
  • 【Robomaster-ICRA-AI挑战赛跳坑篇】(二、TX2刷机)

    TX2刷机与程序下载 TX2安装在步兵车上作为机载计算机使用 xff0c 跑上层代码 xff0c RoboRTS代码托管在github上 xff1a https github com RoboMaster RoboRTS xff0c 目前一
  • 字符串目录判断

    tcschr tcsrchr 好处 xff1a 是可以不管是用unicode 编码还是其他 代码都不用改 C 43 43 标准库函数提供了字符和字符串的操作函数 xff0c 并提供了其UNICODE版本 xff0c 如 xff1a 1 tc
  • @Bean放入其引用Bean中初始化失败分析

    以下讨论的问题及术语均在SpringBoot框架下 xff0c 问题十分小众 xff0c 仅做整理记录 1 先说重点 Bean依赖属性的注入顺序 xff0c 与代码定义顺序无关 xff1b 最好是将 64 Bean注解配置的Bean放在 6
  • MPU6050+HMC5883+BMP180+GPS导航系统设计

    老师有个项目 xff0c 让我搞惯导这一块 虽然最后也没有用上廉价的MPU6050 xff0c 而是用了一两万的Xsens 但是本人还是想写一下MPU6050 xff0c 虽然技术含量不高 xff0c 但是写下来 xff0c 留个纪念吧 首
  • 使用BeanCopier抛出NullPointerException溯源

    问题 使用cglib提供的net sf cglib beans BeanCopier进行对象拷贝时 xff0c 抛出如下异常 xff1a Exception in thread span class token string 34 main