Spring:ReflectionUtils工具类使用一:Field

1 前言

spring-core依赖中,带有反射工具类ReflectionUtils,导包如下:

import org.springframework.util.ReflectionUtils;


2 Field相关使用

(1)ReflectionUtils.makeAccessible、ReflectionUtils.findField使用:

实际上,ReflectionUtils.makeAccessible本质就是调用field.setAccessible(true),让非public修饰的字段,可以操作如protected、private修饰的字段。如下,ReflectionUtils.findField不使用ReflectionUtils.makeAccessible也是可以的,但是ReflectionUtils.getField是需要使用的。

新建注解类MyFruit:

package com.xiaoxu.annotation;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface MyFruit {String fruitName();int number();
}

新建一个DTO类:FruitDTO:

package com.xiaoxu.dto;import com.xiaoxu.annotation.MyFruit;
import org.springframework.util.ReflectionUtils;import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;/*** @author xiaoxu* @date 2022-02-14* Ymybatis:com.xiaoxu.dto.FruitDto*/
public class FruitDto {@MyFruit(fruitName = "荔枝",number = 1)private String one;@MyFruit(fruitName = "菠萝",number = 2)private String two;public static void main(String[] args) {Class<FruitDto> clazz = FruitDto.class;Field[] f = clazz.getDeclaredFields();System.out.println(Arrays.toString(f));Map<Integer,Field> m = new HashMap<>();for (Field field : f) {System.out.println("*********开始*********");System.out.printf("我是field:%s%n",field);String fieldName = field.getName();System.out.printf("我是字段名:%s%n",fieldName);Field field1 = ReflectionUtils.findField(clazz, fieldName);if(field1 !=null){ReflectionUtils.makeAccessible(field1);}System.out.printf("ReflectionUtils的findField方法获取字段:%s%n",field1);// 如果字段具有MyFruit注解if(field.isAnnotationPresent(MyFruit.class)){MyFruit myFruit = field.getAnnotation(MyFruit.class);System.out.printf("字段field调用getAnnotation获取注解:%s%n",myFruit);System.out.printf("map.put返回值为null,说明key不重复:%s%n",m.put(myFruit.number(),field));System.out.printf("map.put返回值为value(这里是Filed的name),说明key重复了:%s%n",m.put(myFruit.number(),field).getName());System.out.printf("获取注解的fruitName:%s%n",myFruit.fruitName());System.out.printf("获取注解的number:%s%n",myFruit.number());}System.out.println("*********结束*********");}System.out.printf("字典如下:%s%n",m);for(Map.Entry<Integer,Field> e:m.entrySet()){System.out.printf("字典的key:%s,value:%s%n",e.getKey(),e.getValue());System.out.println(e.getValue().getAnnotation(MyFruit.class).fruitName());System.out.println(e.getValue().getAnnotation(MyFruit.class).number());}}
}

执行结果如下:

[private java.lang.String com.xiaoxu.dto.FruitDto.one, private java.lang.String com.xiaoxu.dto.FruitDto.two]
*********开始*********
我是field:private java.lang.String com.xiaoxu.dto.FruitDto.one
我是字段名:one
ReflectionUtils的findField方法获取字段:private java.lang.String com.xiaoxu.dto.FruitDto.one
字段field调用getAnnotation获取注解:@com.xiaoxu.annotation.MyFruit(fruitName=荔枝, number=1)
map.put返回值为null,说明key不重复:null
map.put返回值为value(这里是Filed的name),说明key重复了:one
获取注解的fruitName:荔枝
获取注解的number:1
*********结束*********
*********开始*********
我是field:private java.lang.String com.xiaoxu.dto.FruitDto.two
我是字段名:two
ReflectionUtils的findField方法获取字段:private java.lang.String com.xiaoxu.dto.FruitDto.two
字段field调用getAnnotation获取注解:@com.xiaoxu.annotation.MyFruit(fruitName=菠萝, number=2)
map.put返回值为null,说明key不重复:null
map.put返回值为value(这里是Filed的name),说明key重复了:two
获取注解的fruitName:菠萝
获取注解的number:2
*********结束*********
字典如下:{1=private java.lang.String com.xiaoxu.dto.FruitDto.one, 2=private java.lang.String com.xiaoxu.dto.FruitDto.two}
字典的key:1,value:private java.lang.String com.xiaoxu.dto.FruitDto.one
荔枝
1
字典的key:2,value:private java.lang.String com.xiaoxu.dto.FruitDto.two
菠萝
2

(2)ReflectionUtils.doWithFields使用:

注解MFruit:

package com.xiaoxu.annotations;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface MFruit {String name();long num();
}


dto下新建PreciousFruit类:

package com.xiaoxu.dto;import com.xiaoxu.annotations.MFruit;
import org.springframework.util.ReflectionUtils;import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;/*** @author xiaoxu* @date 2022-02-14 22:26* mybatis_learn:com.xiaoxu.dto.PreciousFruit*/
public class PreciousFruit {@MFruit(name = "芒果",num = 1)private String fruitOne;@MFruit(name = "猕猴桃",num = 2)private String fruitTwo;@MFruit(name = "香蕉",num = 3)public String fruitThree;@MFruit(name = "砂糖橘",num = 4)protected String fruitFour;public static Map<Long,Field> injectMethod(){Map<Long,Field> m = new HashMap<>();ReflectionUtils.doWithFields(PreciousFruit.class,// FieldCallback是一个函数式接口,所以可以使用lambda表达式,// 也可以使用方法引用,或者直接new 重写接口的doWith方法new ReflectionUtils.FieldCallback() {@Overridepublic void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {System.out.println("我是回调,哈哈哈哈");if(field.isAnnotationPresent(MFruit.class)){System.out.printf("字段:%s;具有注解MFruit%n",field);long number = field.getAnnotation(MFruit.class).num();if(m.put(number,field)!=null){System.out.println("该水果number重复,跳过");}}System.out.println("********");}});return m;}public static void main(String[] args) {Map<Long, Field> longFieldMap = PreciousFruit.injectMethod();longFieldMap.forEach((k,v)->System.out.printf("map的key:%s,value:%s%n",k,v));}
}

执行结果:

我是回调,哈哈哈哈
字段:private java.lang.String com.xiaoxu.dto.PreciousFruit.fruitOne;具有注解MFruit
********
我是回调,哈哈哈哈
字段:private java.lang.String com.xiaoxu.dto.PreciousFruit.fruitTwo;具有注解MFruit
********
我是回调,哈哈哈哈
字段:public java.lang.String com.xiaoxu.dto.PreciousFruit.fruitThree;具有注解MFruit
********
我是回调,哈哈哈哈
字段:protected java.lang.String com.xiaoxu.dto.PreciousFruit.fruitFour;具有注解MFruit
********
map的key:1,value:private java.lang.String com.xiaoxu.dto.PreciousFruit.fruitOne
map的key:2,value:private java.lang.String com.xiaoxu.dto.PreciousFruit.fruitTwo
map的key:3,value:public java.lang.String com.xiaoxu.dto.PreciousFruit.fruitThree
map的key:4,value:protected java.lang.String com.xiaoxu.dto.PreciousFruit.fruitFourProcess finished with exit code 0

(3)ReflectionUtils.getField使用:

ReflectionUtils.getField本质是调用的field.get(target),getField获取对象该字段的值时,引用类型若未使用setter赋值,那么默认值就是null。另外,ReflectionUtils.getField使用时,若是protected或者private修饰的字段,需先使用ReflectionUtils.makeAccessible(field)。

package com.xiaoxu.dto;import com.xiaoxu.annotation.MyFruit;
import org.springframework.util.ReflectionUtils;import java.lang.reflect.Field;
import java.lang.reflect.Modifier;/*** @author xiaoxu* @date 2022-02-15 21:31* mybatis_learn:com.xiaoxu.dto.FruitDto*/
public class FruitDto {@MyFruit(fruitName = "荔枝",number = 1)public String one;@MyFruit(fruitName = "菠萝",number = 2)private String two;@MyFruit(fruitName = "车厘子",number = 3)protected String three;public void setOne(String one) {this.one = one;}public void setTwo(String two) {this.two = two;}public void setThree(String three) {this.three = three;}public static void main(String[] args) throws IllegalAccessException, InstantiationException {Class<FruitDto> clazz = FruitDto.class;FruitDto cls = clazz.newInstance();Field[] fields = clazz.getDeclaredFields();cls.setThree("nihao");for (Field field : fields) {System.out.printf("我是字段%s%n",field);System.out.printf("我是字段的修饰符:%s%n",field.getModifiers());switch(field.getModifiers()){case 1:System.out.println("我是public");Object filed1 = ReflectionUtils.getField(field,cls);System.out.printf("我是field:%s%n",filed1);break;case 2:System.out.println("我是private");ReflectionUtils.makeAccessible(field);Object filed2 = ReflectionUtils.getField(field,cls);System.out.printf("我是field:%s%n",filed2);break;case 4:System.out.println("我是protected");ReflectionUtils.makeAccessible(field);Object filed3 = ReflectionUtils.getField(field,cls);System.out.printf("我是field:%s%n",filed3);break;default:System.out.println("暂时只支持public、protected、private.");}if(Modifier.isProtected(field.getModifiers())){System.out.println("我是保护的");ReflectionUtils.makeAccessible(field);Object field1 = ReflectionUtils.getField(field, cls);System.out.println(field1);}System.out.println("****************");}}
}

执行结果:

我是字段public java.lang.String com.xiaoxu.dto.FruitDto.one
我是字段的修饰符:1
我是public
我是field:null
****************
我是字段private java.lang.String com.xiaoxu.dto.FruitDto.two
我是字段的修饰符:2
我是private
我是field:null
****************
我是字段protected java.lang.String com.xiaoxu.dto.FruitDto.three
我是字段的修饰符:4
我是protected
我是field:nihao
我是保护的
nihao
****************

(4)ReflectionUtils.setField使用:

实体类中重写toString便于观察,无需加入setter方法。且使用ReflectionUtils.setField前,也需要为private、protected修饰的字段执行setAccessible(ture)操作。

package com.xiaoxu.dto;import com.xiaoxu.annotations.MyFruit;
import org.springframework.util.ReflectionUtils;import java.lang.reflect.Modifier;
import java.util.Arrays;/*** @author xiaoxu* @date 2022-02-16 22:31* mybatis_learn:com.xiaoxu.dto.FruitDto2*/
public class FruitDto2 {@MyFruit(fruitName = "牛油果",number = 1)public String one;@MyFruit(fruitName = "葡萄",number = 2)private String two;@MyFruit(fruitName = "桃子",number = 3)protected String three;@Overridepublic String toString() {return "水果2{" +"one='" + one + '\'' +", two='" + two + '\'' +", three='" + three + '\'' +'}';}public static void main(String[] args) throws IllegalAccessException, InstantiationException {Class<? extends FruitDto2> clazz = FruitDto2.class;FruitDto2 f = clazz.newInstance();Arrays.stream(clazz.getDeclaredFields()).forEach(field->{System.out.println(field);if(Modifier.isPrivate(field.getModifiers())||Modifier.isProtected(field.getModifiers())){ReflectionUtils.makeAccessible(field);}ReflectionUtils.setField(field,f,"one");});System.out.println(f);}
}

结果如下:

public java.lang.String com.xiaoxu.dto.FruitDto2.one
private java.lang.String com.xiaoxu.dto.FruitDto2.two
protected java.lang.String com.xiaoxu.dto.FruitDto2.three
水果2{one='one', two='one', three='one'}

Spring:ReflectionUtils工具类使用一:Field相关推荐

  1. Spring Redis工具类

    /*** spring redis 工具类**/ @Component @SuppressWarnings(value = { "unchecked", "rawtype ...

  2. Spring 计时工具类 StopWatch

    Spring 计时工具类 StopWatch 位于Spring的核心包 设计目标 验证程序性能, 记录过程耗时 隐藏System.currentTimeMillis()的使用提升代码可读性 特性 支持 ...

  3. Java实现代码计时功能(Spring计时工具类--StopWatch学习总结)

    使用场景 计算某段程序的执行时间.计算每段线程所耗时间.计算方法调用的执行时间,等等. 传统方式 使用java代码实现计时功能 long startTime = System.currentTimeM ...

  4. Spring常用工具类

    Spring框架下自带了丰富的工具类,在我们开发时可以简化很多工作: 1.Resource访问文件资源: 具体有: ResourceUtils.getFile(url); FileSystemReso ...

  5. Spring的工具类,方便在非spring管理环境中获取bean

    场景 在SpringBoot的后台项目中,如果想要引入并且调用某个bean,可以直接通过注解的方式. 比如在单元测试中引入某业务的Controller @RunWith(SpringJUnit4Cla ...

  6. spring注解工具类AnnotatedElementUtils和AnnotationUtils

    一.前言 spring为开发人员提供了两个搜索注解的工具类,分别是AnnotatedElementUtils和AnnotationUtils.在使用的时候,总是傻傻分不清,什么情况下使用哪一个.于是我 ...

  7. Spring 常用工具类

    1) 请求工具类 org.springframework.web.bind.ServletRequestUtils //取请求参数的整数值: public static Integer getIntP ...

  8. SpringBoot中操作spring redis的工具类

    场景 SpringBoot+Vue+Redis实现前后端分离的字典缓存机制: https://blog.csdn.net/badao_liumang_qizhi/article/details/108 ...

  9. 解决spring的读取文件的工具类来获取文件等操作

    今天项目又遇到了,,,读取项目下文件的情况下. 其实这个挺头疼的,,,特别是 Java web项目 下的方式和 Java 项目 下 读取文件的相对路径是有点区别的...所以感觉挺不好搞的... 而且 ...

  10. Java-开发常用工具类

    目录 1.数据比对工具 2.汉字转拼音 3.日期工具类 4.自定义线程池 5.Spring上下文工具类 1.数据比对工具 package com.micecs.erp.util;import com. ...

最新文章

  1. 剑指offer:正则表达式匹配
  2. beeline执行sql语句_由“Beeline连接HiveServer2后如何使用指定的队列(Yarn)运行Hive SQL语句”引发的一系列思考...
  3. 「第四篇」电赛控制题可以准备一些什么?
  4. java是解释型编程语言_程序设计语言可以分为两类:编译型语言和解释型语言...
  5. html引用单文件组件,vue之单文件组件 纯网页方式引入
  6. linux mysql 写shell_Linux—编写shell脚本操作数据库执行sql
  7. 删除a标签下面的横线
  8. kafka发送mysql数据丢失_Kafka 如果丢了消息,怎么处理的?
  9. 如何让webpack打包的速度提升50%?
  10. 汇编语言程序设计基础知识
  11. java进制转换所有方法_Java进制转换方法整理
  12. sqlite3数据库函数
  13. ML语言/函数式编程原理(一)
  14. poi填充word模板
  15. 【linux内核分析与应用-陈莉君】文件系统
  16. 计算机无法对NAS硬盘操作,群晖NAS联机失败不要慌,我用经验告诉你,这样做就能完美解决...
  17. Unity获取天气最稳定的接口
  18. 俞敏洪:快乐是一种选择
  19. c#怎么在github上快速找到相关的开源项目
  20. 领悟《信号与系统》之 信号与系统的描述-上节

热门文章

  1. 技术岗网上测评-智力题
  2. fastdb中的位图应用
  3. 信息收集 | 利用Google搜索语法进行Google Hacking
  4. 用c语言输入年份 月份 显示天数,java输入月份,年份,显示对应月份的天数,...
  5. 电信行业数据安全风险评估案例 - 数据安全治理之数据安全风险评估白皮书
  6. Apple 宣布 2021 年 Apple Design Awards 获奖者
  7. 杂项-公司:Apple
  8. 制作u盘winpe启动盘_U盘PE启动盘制作方法
  9. 免费站群系统cm-SEO需要多长时间?
  10. 使用 hydra 破解路由器密码