浅学java反射二:反射在项目中的应用

279 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第6天,点击查看活动详情

前言:

如果有人问我如何提升代码的简洁度,反射一定在我的回答里面。工作了一些年,呆过几个公司,发现大家都知道反射也知道反射的一些常用api,但是应用在项目中的还是很少,下面我举例几个在业务开发中可以用到反射的地方。

一丶检验参数是否全部填写

我们在工作中经常会遇到这样的需求,前端页面的一些表单字段必须全部填写才能提交表单,这里一般前端会在页面上校验参数是否填写,但是如果只做了前端的校验,其实我们可以通过直接调用接口的方式发送请求,这个时候我们就需要在后端也校验一下参数是否全部填写,一般页面的表单会对应数据库的一个或者多个实体,下面我们以User对象举例,来看看反射校验参数是否全部填写的场景。

  • 实体
@Data
public class User {
    private Long id;

    private String name;
    
    private Integer age;

    private Integer sex;
}
  • 普通方式校验参数是否必填
private void checkUserRequired(User user) {
    if (Objects.isNull(user.getAge())
            || Objects.isNull(user.getSex())
            || StringUtils.isEmpty(user.getName())) {
        throw new RuntimeException("Please complete the form before submitting.");
    }
}
  • 使用反射校验参数是否必填
private <T> void checkUserRequiredReflect(T t) throws IllegalAccessException {
    Class<?> clzss = t.getClass();
    Field[] fields = clzss.getDeclaredFields();
    for (Field field : fields) {
        String name = field.getName();
        if (Objects.equals(ID, name)) {
            continue;
        }
        if (Objects.isNull(field.get(t))) {
            throw new RuntimeException("Please complete the form before submitting.");
        }            
    }
}

二丶填充通用字段

现在我们数据库表一般都会有几个通用字段,比如更新人,更新时间,创建人,创建时间,是否删除等。例如:我们在删除的时候都要更新更新人、更新时间、是否删除字段,我们这里就可以用反射来写一个通用的方法。

  • 实体
@Data
public class User {
    private Long id;

    private String name;
    
    private Integer age;

    private Integer sex;
    
    private Long updateUser;
    
    private Date updateTime;
    
    private Integer isDelete;
}
  • 普通方式填充通用字段
private void buildUserDeleted(User user) {
    user.setUpdateUser(111l);
    user.setUpdateTime(new Date());
    user.setIsDelete(1);
}
  • 使用反射填充通用字段
private <T> void buildEntityDeletedByReflect(T t) throws IllegalAccessException {
    Class<?> clzss = t.getClass();
    Field[] fields = clzss.getDeclaredFields();
    for (Field field : fields) {
        String name = field.getName();
        if (Objects.equals("updateUser", name)) {
            field.set(t, 111l);
            continue;
        }
        if (Objects.equals("updateTime", name)) {
            field.set(t, new Date());
            continue;
        }
        if (Objects.equals("isDelete", name)) {
            field.set(t, 1);
        }
    }
}

总结

可能看到上面的例子有人说,你填充字段写了那么多代码,我设置三个属性就三行代码就行了,但是普通方式填充通用字段,我们一个实体就需要写一个那样的build方法,而我们通过反射的方式设置字段值,可以用在任何的实体对象上面(存在这三个字段的实体类)。相信大家看到这里发现反射的好处,我们可以不用显示指定对象的类型来操作一个对象,我们将之前需要编译期就确定对象类型延后到了运行期去了,这样我们就可以针对对象做一些通用的操作。