简介
说明
本文介绍Spring的BeanUtils工具类的用法。
我们经常需要将不同的两个对象实例进行属性复制,比如将DO对象进行属性复制到DTO,这种转换最原始的方式就是手动编写大量的 get/set代码,很繁琐。为了解决这一痛点,就诞生了一些方便的类库,常用的有 Apache的 BeanUtils,Spring的 BeanUtils, Dozer,Orika等拷贝工具。
由于Apache的BeanUtils的性能很差,强烈不建议使用。阿里巴巴Java开发规约插件上也明确指出:
“Ali-Check | 避免用Apache Beanutils进行属性的copy。”
Spring的BeanUtils方法
方法 | 说明 |
BeanUtils.copyProperties(source, target); | source对应的对象成员赋值给target对应的对象成员 |
BeanUtils.copyProperties(source, target, “id”, “time”); | 忽略拷贝某些字段。本处是忽略:id与time |
Spring的BeanUtils方法注意事项
- BeanUtils是浅拷贝。
- 泛型只在编译期起作用,不能依靠泛型来做运行期的限制;
浅拷贝和深拷贝
- 浅拷贝:对基本数据类型进行值传递,对引用数据类型,使用其引用地址,不拷贝其内容,此为浅拷贝
- 深拷贝:对基本数据类型进行值传递,对引用数据类型,创建一个新的对象,并复制其内容,此为深拷贝。
Spring的BeanUtils与Apache的BeanUtils区别
项 | Spring的BeanUtils | Apache的BeanUtils |
性能 | 好。 原因:对两个对象中相同名字的属性进行简单的get/set,仅检查属性的可访问性 | 差。 原因:有很多检验:类型的转换、对象所属类的可访问性等 注意:本处类型转换是类似的类,多个String转为List<String>是不行的。 |
使用方面 | 第一个参数是源,第二个参数是目标。 无需捕获异常 | 第一个参数是目标,第二个参数是源。 必须捕获异常 |
深/浅拷贝 | 浅拷贝 | 浅拷贝 |
Apache的BeanUtils方法。(依赖:maven里直接搜“commons-beanutils”)
方法 | 说明 |
BeanUtils.copyProperties(Object target, Object source); | source对应的对象成员赋值给target对应的对象成员 |
BeanUtils.copyProperties(Object target, String name, Object source); | 只拷贝某些字段。 |
Apache的BeanUtils支持的类型转换
- java.lang.BigDecimal
- java.lang.BigInteger
- boolean and java.lang.Boolean
- byte and java.lang.Byte
- char and java.lang.Character
- java.lang.Class
- double and java.lang.Double
- float and java.lang.Float
- int and java.lang.Integer
- long and java.lang.Long
- short and java.lang.Short
- java.lang.String
- java.sql.Date
- java.sql.Time
- java.sql.Timestamp
java.util.Date是不被支持的,而它的子类java.sql.Date是被支持的。因此如果对象包含时间类型的属性,且希望被转换的时候,一定要使用java.sql.Date类型。否则在转换时会提示argument mistype异常。
实例
entity
package com.example.entity; import lombok.Data; @Data public class Question { private Integer id; private Integer studentId; private String content; private Integer value; }
package com.example.entity; import lombok.Data; @Data public class Student { private Integer id; private String name; private Integer points; }
vo
package com.example.vo; import lombok.Data; import java.io.Serializable; import java.util.List; @Data public class QuestionStudentVO implements Serializable { private Integer id; private String content; private Integer value; private Integer studentId; private List<String> name; private Integer points; }
测试类
package com.example; import com.example.entity.Question; import com.example.entity.Student; import com.example.vo.QuestionStudentVO; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.BeanUtils; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest public class DemoApplicationTests { @Test public void beanUtilTest(){ Question question = new Question(); question.setId(2); // question.setStudentId(3); question.setContent("This is content"); question.setValue(100); Student student = new Student(); student.setId(3); student.setName("Tony Stark"); student.setPoints(201); QuestionStudentVO questionStudentVO = new QuestionStudentVO(); BeanUtils.copyProperties(question, questionStudentVO); BeanUtils.copyProperties(student, questionStudentVO); System.out.println(questionStudentVO); } }
执行结果
QuestionStudentVO(id=3, content=This is content, value=100, studentId=null, name=null, points=201)
请先
!