spring反射工具类的使用 ReflectionUtils.doWithFields
背景
当我们导入一个表格时,某些单元只能填写数字,当填写中文、英文以及其他特殊符号时,将该字段处理成null;
一个个字段多判断,如果字段少还好,要是字段特别多,将会写大量的重复性代码,于是可以用注解加上反射来实现。
实现
注解定义:
// 自定义注解
@Target(ElementType.FIELD)
@Documented
@Inherited
@JacksonAnnotation
@Retention(RetentionPolicy.RUNTIME)
public @interface BigDecimalAnnotation {
}
// 实体类引用
@ApiModelProperty(value = "序号")
@ExcelProperty(index = 0)
private String number;
@ApiModelProperty(value = "科目名字")
@ExcelProperty(index = 1)
private String detailSubjectName;
/**
* 两年前实际数
*/
@ApiModelProperty(value = "两年前实际数")
@ExcelProperty(index = 2)
@BigDecimalAnnotation
private String twoYearLastRealityNumber;
/**
* 去年预算
*/
@ApiModelProperty(value = "去年预算")
@ExcelProperty(index = 3)
@BigDecimalAnnotation
private String lastYearBudget;
带有@BigDecimalAnnotation注解的字段,必须是数字,如果不是数字转换成null;
反射实现:
/**
* 数据转换和校验
*/
private void dataCheck(XinghuiDetailVo vo) {
// 反射
ReflectionUtils.doWithFields(vo.getClass(), field -> {
// 暴力反射
field.setAccessible(true);
// 判断注解
BigDecimalAnnotation annotation = field.getAnnotation(BigDecimalAnnotation.class);
if (annotation == null) {
return;
}
String value = (String) field.get(vo);
log.debug("value:{}", value);
// 避免空值
if (StringUtils.isBlank(value)) {
return;
}
// 判断字段是否为数字
String str = value.replace("%", "").replace(",", "");
boolean numericzidai = RegularExpression.isNumericzidai(str);
// 设置对应值
if (!numericzidai) {
field.set(vo, null);
} else {
field.set(vo, str);
}
});
}
扩展
自定义注解时常用注解
@Target
@Target:注解的作用目标
@Target(ElementType.TYPE)——接口、类、枚举、注解
@Target(ElementType.FIELD)——字段、枚举的常量
@Target(ElementType.METHOD)——方法
@Target(ElementType.PARAMETER)——方法参数
@Target(ElementType.CONSTRUCTOR) ——构造函数
@Target(ElementType.LOCAL_VARIABLE)——局部变量
@Target(ElementType.ANNOTATION_TYPE)——注解
@Target(ElementType.PACKAGE)——包,用于记录java文件的package信息
@Retention
@Retention作用是定义被它所注解的注解保留多久,一共有三种策略,定义在RetentionPolicy枚举中.
从注释上看:
source:注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃;被编译器忽略
class:注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期
runtime:注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在
这3个生命周期分别对应于:Java源文件(.java文件) —> .class文件 —> 内存中的字节码
@Inherited
@Inherited 注解修饰的注解,如果作用于某个类上,其子类是可以继承的该注解的。反之,如果一个注解没有被 @Inherited注解所修饰,那么他的作用范围只能是当前类,其子类是不能被继承的。
@Documented
作用:生成文档信息的时候保留注解,对类作辅助说明