努力了这么久,但凡有点儿天赋,也该有些成功的迹象了。
前言
最近做的一个项目需要经常给对象赋值,或者说把一个数据库的实体对象转化成elasticsearch中的存储对象,要是属性没几个,倒是还好点,几行set方法就搞定了,要是对象的属性一多,几十个上百个属性,那完犊子了,写上几十上百行的set方法,那种代码体验着实让人想吐,比如像下面这个样子:
一屏幕都截取不完,看上边图片上右下角标红的那部分代码小地图,这也就五十个左右的属性,我就写了这么一次都要疯掉了,当我看到另一个对象里有158个属性的时候我就彻底崩溃了。我绝对绝对不想再体验一次了。于是我就想着能不能用反射来获取所有的属性,然后通过循环给对象赋值。说干就干,接下来我们开始进入正题。
首先引入Hutool包
自从我知道了这个包之后我就太喜欢这个工具包了。真的是想要什么工具都有,我就是试一试看看它有没有反射工具包,没想到它还真的有。那么我们就先引入Hutool吧:
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-core</artifactId>
<version>5.2.4</version>
</dependency>
准备两个对象
然后我们先准备两个类,用来互相转化,一个VblogUser,一个UserDTO。用反射来获取VblogUser的值并赋值给UserDTO。简单起见,我们两个类的属性一模一样。
@Data
public class VblogUser {
private Long id; //主键
private String username; //用户名
private String password; //密码
private String nickname; //昵称
private boolean enabled; //是否禁用
private String email; //邮箱
private String userface; //头像
private String regTime; //注册时间
}
---------------------------------------------------------------------------
@Data
public class UserDTO {
private Long id; //主键
private String username; //用户名
private String password; //密码
private String nickname; //昵称
private boolean enabled; //是否禁用
private String email; //邮箱
private String userface; //头像
private String regTime; //注册时间
}
模拟数据
接下来我们写个方法给VblogUser 对象赋值。假装我们是从数据库里查询出来的数据。
/**
* 创建对象,模拟数据
* @return
*/
public static VblogUser creatUser(){
VblogUser user = new VblogUser();
user.setId(1024L);
user.setNickname("朽木");
user.setPassword("123456");
user.setUsername("亚索");
user.setEmail("1234566665@qq.com");
user.setUserface("xiumu.jpg");
user.setEnabled(true);
user.setRegTime(DateUtil.now());
return user;
}
反射实现赋值的思路
通过我的实验,使用Field直接调用set方法,或者用Hutool反射工具类里边的setFieldValue方法来进行赋值是有问题的,会报异常,然后我又没解决它,所以我就换了个方式来进行赋值。
首先获取对象所有的属性并进行循环
然后根据属性名字生成这个属性的set方法名
再调用这个set方法进行赋值
开始写对象转化工具类
首先我们需要创建一个工具类,写上两个通用方法。第一个方法就是根据属性名字生成set方法名。我们知道set方法名一般就是把属性首字母大写,然后加上一个set
前缀。
/**
* 根据属性名获取set方法名
* @param fieldName 属性名
* @return
*/
private static String getSetMethodName(String fieldName) {
char[] field = fieldName.toCharArray();
//首字母大写
field[0] -= 32;
//加上set前缀
return "set"+String.valueOf(field);
}
第二个方法就是调用该对象的set方法给属性赋值。
/**
* 给目标对象赋值
* @param userDTO 目标对象
* @param fieldName 属性名
* @param value 值
*/
private static void setFieldValue(UserDTO userDTO, String fieldName, Object value) {
//使用Hutool的反射工具类获取set方法
Method method = ReflectUtil.getMethodByName(userDTO.getClass(),getSetMethodName(fieldName));
//使用Hutool的反射工具类调用set方法给对象赋值
ReflectUtil.invoke(userDTO,method,value);
}
接下来就是获取所有的属性并循环给对象赋值。
/**
* 将VblogUser转化成userDTO
* @param user
* @return
*/
public static UserDTO transformUser(VblogUser user){
UserDTO userDTO = new UserDTO();
//获取对象所有的属性
Field[] fields = ReflectUtil.getFields(UserDTO.class);
for (Field field : fields) {
//根据属性名获取属性的值
Object value = ReflectUtil.getFieldValue(user, field.getName());
if (value != null){
//给对象赋值
setFieldValue(userDTO,field.getName(),value);
}
}
return userDTO;
}
测试结果
接下来我们写个main方法来测试一下这个工具好不好用。
public static void main(String[] args) {
VblogUser vblogUser = creatUser();
System.out.println(vblogUser);
UserDTO userDTO = BeanTransformUtil.transformUser(vblogUser);
System.out.println(userDTO);
}
结果截图:
我们可以看到,这个方法还是挺好的,只要写好了工具类,只需要用这短短几行代码就可以完成对象与对象之间的赋值。