Spring:ReflectionUtils工具类使用一:Field
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相关推荐
- Spring Redis工具类
/*** spring redis 工具类**/ @Component @SuppressWarnings(value = { "unchecked", "rawtype ...
- Spring 计时工具类 StopWatch
Spring 计时工具类 StopWatch 位于Spring的核心包 设计目标 验证程序性能, 记录过程耗时 隐藏System.currentTimeMillis()的使用提升代码可读性 特性 支持 ...
- Java实现代码计时功能(Spring计时工具类--StopWatch学习总结)
使用场景 计算某段程序的执行时间.计算每段线程所耗时间.计算方法调用的执行时间,等等. 传统方式 使用java代码实现计时功能 long startTime = System.currentTimeM ...
- Spring常用工具类
Spring框架下自带了丰富的工具类,在我们开发时可以简化很多工作: 1.Resource访问文件资源: 具体有: ResourceUtils.getFile(url); FileSystemReso ...
- Spring的工具类,方便在非spring管理环境中获取bean
场景 在SpringBoot的后台项目中,如果想要引入并且调用某个bean,可以直接通过注解的方式. 比如在单元测试中引入某业务的Controller @RunWith(SpringJUnit4Cla ...
- spring注解工具类AnnotatedElementUtils和AnnotationUtils
一.前言 spring为开发人员提供了两个搜索注解的工具类,分别是AnnotatedElementUtils和AnnotationUtils.在使用的时候,总是傻傻分不清,什么情况下使用哪一个.于是我 ...
- Spring 常用工具类
1) 请求工具类 org.springframework.web.bind.ServletRequestUtils //取请求参数的整数值: public static Integer getIntP ...
- SpringBoot中操作spring redis的工具类
场景 SpringBoot+Vue+Redis实现前后端分离的字典缓存机制: https://blog.csdn.net/badao_liumang_qizhi/article/details/108 ...
- 解决spring的读取文件的工具类来获取文件等操作
今天项目又遇到了,,,读取项目下文件的情况下. 其实这个挺头疼的,,,特别是 Java web项目 下的方式和 Java 项目 下 读取文件的相对路径是有点区别的...所以感觉挺不好搞的... 而且 ...
- Java-开发常用工具类
目录 1.数据比对工具 2.汉字转拼音 3.日期工具类 4.自定义线程池 5.Spring上下文工具类 1.数据比对工具 package com.micecs.erp.util;import com. ...
最新文章
- 剑指offer:正则表达式匹配
- beeline执行sql语句_由“Beeline连接HiveServer2后如何使用指定的队列(Yarn)运行Hive SQL语句”引发的一系列思考...
- 「第四篇」电赛控制题可以准备一些什么?
- java是解释型编程语言_程序设计语言可以分为两类:编译型语言和解释型语言...
- html引用单文件组件,vue之单文件组件 纯网页方式引入
- linux mysql 写shell_Linux—编写shell脚本操作数据库执行sql
- 删除a标签下面的横线
- kafka发送mysql数据丢失_Kafka 如果丢了消息,怎么处理的?
- 如何让webpack打包的速度提升50%?
- 汇编语言程序设计基础知识
- java进制转换所有方法_Java进制转换方法整理
- sqlite3数据库函数
- ML语言/函数式编程原理(一)
- poi填充word模板
- 【linux内核分析与应用-陈莉君】文件系统
- 计算机无法对NAS硬盘操作,群晖NAS联机失败不要慌,我用经验告诉你,这样做就能完美解决...
- Unity获取天气最稳定的接口
- 俞敏洪:快乐是一种选择
- c#怎么在github上快速找到相关的开源项目
- 领悟《信号与系统》之 信号与系统的描述-上节