Springboot工具类ReflectionUtils使用教程

目录
  • 前言
  • ReflectionUtils
    • 对属性的操作
    • 对方法的操作

前言

ReflectionUtils应该是Springboot内置工具类梳理的最后一篇了,可能很多人都没有听说过这个工具类,这个类封装的是一些与java反射相关的静态工具方法。可能很多人也知道反射,却不怎么经常使用反射。其实反射是一个很有用的技术点,我认为是可以和AOP比肩的,甚至有过之而不及。大家都知道AOP是面向切面编程,可以在定义的切面前、后执行一些操作,但是反射更厉害,它可以在程序运行时,对已装载的任意类的属性和方法进行操作,这就是java的反射机制。

ReflectionUtils

org.springframework.util.ReflectionUtils中包含的静态方法其实有很多,主要分为两类:对类中属性的操作和对类中方法的操作。

对属性的操作

获取属性字段

Field findField(Class clazz,Stringname),在类中查找指定属性。

@Test
public void test1(){
    //查找属性字段realName
    Field realName = ReflectionUtils.findField(Employee.class, "realName");
    Assert.notNull(realName, "获取员工类的姓名属性失败");
}

Field findField(Class clazz,Stringname, Classtype),更精确的在类中查找指定属性,可以在指定属性的类型。

@Test
public void test2(){
     //查找属性字段realName,类型是String
    Field realName = ReflectionUtils.findField(Employee.class, "realName",String.class);
    Assert.notNull(realName, "获取员工类的姓名属性失败");
}

设置属性字段的值

ObjectgetField(Field field,Objecttarget),获取 target 对象的 field 属性值。

@Test
public void test3() {
    //声名一个对象,姓名是zhangsan
    Employee zhangsan = new Employee("zhangsan");
    //获取Employee类中的realName属性字段
    Field field = ReflectionUtils.findField(Employee.class, "realName");
    //取消realName属性的private权限控制
    ReflectionUtils.makeAccessible(field);
    //获取员工对象的姓名字段的值
    Object value = ReflectionUtils.getField(field, zhangsan);
    Assert.isTrue(value.equals("zhangsan"),"员工zhangsan的姓名字段取值失败" );
}

voidsetField(Field field,Objecttarget,Objectvalue),可以设置 target 对象的 field 属性值,值为 value。

@Test
public void test4() {
    Employee zhangsan = new Employee("zhangsan");
    //获取Employee类中的realName属性字段
    Field field = ReflectionUtils.findField(Employee.class, "realName");
    //取消realName属性的private权限控制
    ReflectionUtils.makeAccessible(field);
    //把员工对象zhangsan的姓名字段值设置为zhangsan_v2
    ReflectionUtils.setField(field, zhangsan, "zhangsan_v2");
    Object value = ReflectionUtils.getField(field, zhangsan);
    Assert.isTrue(value.equals("zhangsan_v2"),"员工zhangsan的姓名字段取值失败" );
}

voidshallowCopyFieldState(Objectsrc,Objectdest),如果两个对象是同一个类的实现,且希望把一对象的值复制到另外一个对象上,可以使用这个方法,src是源对象,dest是目标对象。

@Test
public void test5() {
    Employee zhangsan = new Employee("zhangsan");
    Employee tmp = new Employee();
    //把对象zhangsan的值复制到对象tmp上,这里要注意,复制的对象类型要相同
    ReflectionUtils.shallowCopyFieldState(zhangsan, tmp);
    Assert.isTrue(tmp.getRealName().equals("zhangsan"),"对象的属性复制失败了" );
}

voidmakeAccessible(Field field),取消java的权限控制检查,方便private私有访问权限的操作。

@Test
public void test4() {
    Employee zhangsan = new Employee("zhangsan");
    //取消realName属性的private权限控制
    ReflectionUtils.makeAccessible(field);
}

voiddoWithFields(Class clazz, ReflectionUtils.FieldCallback fc),可以对类的每个属性执行 回调方法,简单的理解就是可以定义一个回调方法,在对类的属性操作完后,回调方法内的逻辑就会被执行。另外还有两个方法,功能也很类似:void doWithFields(Class clazz, ReflectionUtils.FieldCallback fc,ReflectionUtils.FieldFilter ff),不仅有回调方法,还可以增加过滤的逻辑;voiddoWithLocalFields(Class clazz, ReflectionUtils.FieldCallback fc),只对本类的属性可以执行回调方法,不包括父类的。举个例子,简单的理解一下,实在理解不了就放弃吧,因为我也觉得这个确实有点鸡肋。假如员的性别在程序中是以1和0进行区分,对外展示的时候要转换为“男”和“女”:

public class  SexFieldCallBack<T>  implements ReflectionUtils.FieldCallback{
    private Object obj;
    private Integer sexFlag=-1;
    public SexFieldCallBack(Object obj) {
        this.obj = obj;
    }
    @Override
    public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
        field.setAccessible(true);
        if (field.getName().equals("sexFlag")) {
            Object value = field.get(obj);
            this.sexFlag= ((Integer) value);
        }
        if(field.getName().equals("sex")){
            if (1==this.sexFlag) {
                field.set(obj, "男");
            }
            if (0==this.sexFlag) {
                field.set(obj, "女");
            }
        }
    }
}
@Test
public void test6() throws IllegalAccessException, InstantiationException {
    Employee employee = Employee.class.newInstance();
    employee.setRealName("zhangsan");
    //性别标志位,1:男,0:女
    employee.setSexFlag(1);
    ReflectionUtils.doWithFields(Employee.class,new SexFieldCallBack(employee) );
    Assert.isTrue("男".equals(employee.getSex()), "性别转换失败了");
}

对方法的操作

@Data
public class Employee implements Serializable {
    private String realName;
    public void hello(String name) {
        System.out.println(name + ",你好!我是" + this.realName);
    }
    public void say(String name) {
        System.out.println(name + ",你好!我是" + this.realName);
    }
    public String hello(String name, Boolean isReturn) {
        String msg = name + ",你好!我是" + this.realName;
        if (isReturn) {
            System.out.println(msg);
            return msg;
        }
        return null;
    }
}

获取方法

Method findMethod(Classclazz,Stringname),在类中查找指定名字方法

@Test
public void test7() throws IllegalAccessException, InstantiationException, InvocationTargetException {
    //查找类中的hello方法
    //这里要注意如果类中有方法名相同的重载方法时,一要要用下面的方法,把参数的类型给带上
    //如果不是重载方法,用这个也没问题
    Method say = ReflectionUtils.findMethod(Employee.class, "say");
    Employee employee = Employee.class.newInstance();
    employee.setRealName("zhangsan");
    say.invoke(employee, "lisi");
}

Method findMethod(Class clazz,Stringname, Class... paramTypes),有的时候同一个类可能会有多个方法名相同,形参数不同的重载方法,可以使用这个方法更精确的在类中找到指定方法;

@Test
public void test8() throws IllegalAccessException, InstantiationException, InvocationTargetException {
    Method hello = ReflectionUtils.findMethod(Employee.class, "hello",String.class,Boolean.class);
    Employee employee = Employee.class.newInstance();
    employee.setRealName("zhangsan");
    //执行employee对象的hello方法
    Object msg = hello.invoke(employee, "lisi",true);
    System.out.println(msg);
}

Method[] getAllDeclaredMethods(Class leafClass),获得类中所有方法,包括继承而来的。

@Test
public void test9()  {
    //获取类中所有的方法,包括继承而来的
    Method[] methods = ReflectionUtils.getAllDeclaredMethods(Employee.class);
    for (Method o : methods) {
        System.out.println(o.getName());
    }
}

执行方法

ObjectinvokeMethod(Method method,Objecttarget),执行无参数的方法;

ObjectinvokeMethod(Method method,Objecttarget,Object... args),执行有参数的方法

voidmakeAccessible(Method method),如果是私有方法,可以取消 Java 权限检查,以便后续执行该私有方法

@Test
public void test10() throws IllegalAccessException, InstantiationException, InvocationTargetException {
    //获取set方法
    Method setRealName = ReflectionUtils.findMethod(Employee.class, "setRealName", String.class);
    //反射实例化一个对象
    Employee employee = Employee.class.newInstance();
    //放开权限检查
    ReflectionUtils.makeAccessible(setRealName);
    //执行set方法
    setRealName.invoke(employee, "zhangsan");
    //获取get方法
    Method getRealName = ReflectionUtils.findMethod(Employee.class, "getRealName");
    //执行get方法
    Object result = getRealName.invoke(employee);
    Assert.isTrue(result.equals("zhangsan"), "getRealName方法执行失败");
}

到此这篇关于Springboot工具类ReflectionUtils使用教程的文章就介绍到这了,更多相关Springboot ReflectionUtils内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Springboot内置的工具类之CollectionUtils示例讲解

    前言 实际业务开发中,集合的判断和操作也是经常用到的,Spring也针对集合的判断和操作封装了一些方法,但是最令我惊讶的是,我在梳理这些内容的过程中发现了一些有趣的现象,我的第一反应是不敢相信,再想一想,没错,我是对的.所以强烈建议大家可以认真看完这篇文章,这一篇绝对有价值,因为有趣的是我我竟然发现了Spring的两个bug. org.springframework.util.CollectionUtils 集合的判断 boolean hasUniqueObject(Collection col

  • 使用springboot在工具类中读取配置文件(ClassPathResource)

    springboot工具类中读取配置文件 1.创建配置文件(application.properties) spring.activemq.broker-url=tcp://localhost:61616 spring.activemq.user=admin spring.activemq.password=admin spring.activemq.in-memory=true spring.activemq.pool.enabled=false 2.创建工具类(PropertiesUtil.

  • Springboot基础之RedisUtils工具类

    SpringBoot整合Redis 引入Redis依赖 <!-- redis--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> 设置Redis的Template RedisConfig.java package cn

  • SpringBoot 内置工具类的使用

    目录 断言 对象.数组.集合 ObjectUtils StringUtils CollectionUtils 文件.资源.IO 流 FileCopyUtils ResourceUtils StreamUtils 反射.AOP ReflectionUtils AopUtils AopContext 断言 断言是一个逻辑判断,用于检查不应该发生的情况 Assert 关键字在 JDK1.4 中引入,可通过 JVM 参数-enableassertions开启 SpringBoot 中提供了 Assert

  • Springboot如何通过自定义工具类获取bean

    目录 Springboot 自定义工具类获取bean 在工具类注入bean的三种方式 1. 需求/目的 2.使用环境 3.方法一:获取ApplicationContext上下文 4.方法二:将工具类的对象也添加为bean 5.方法三:在spring Boot 启动时创建工具类自身的静态对象 Springboot 自定义工具类获取bean /** * Created with IntelliJ IDEA. * * @Auther: zp * @Date: 2021/03/26/13:32 * @D

  • Springboot工具类ReflectionUtils使用教程

    目录 前言 ReflectionUtils 对属性的操作 对方法的操作 前言 ReflectionUtils应该是Springboot内置工具类梳理的最后一篇了,可能很多人都没有听说过这个工具类,这个类封装的是一些与java反射相关的静态工具方法.可能很多人也知道反射,却不怎么经常使用反射.其实反射是一个很有用的技术点,我认为是可以和AOP比肩的,甚至有过之而不及.大家都知道AOP是面向切面编程,可以在定义的切面前.后执行一些操作,但是反射更厉害,它可以在程序运行时,对已装载的任意类的属性和方法

  • Springboot工具类FileCopyUtils使用教程

    目录 前言 Resource FileCopyUtils StreamUtils 前言 Spring内置的工具类里,最喜欢用的就是文件读写这一部分,虽然原生的写法也没几句,但是就是懒,不想循环.判断什么的,直接调用现成的静态方法,多高效,哈哈,这就是懒人必备. Resource Spring中主要通过org.springframework.core.io.Resource接口描述一个文件资源的位置信息,其常用的实现类有四个,分别是FileSystemResource.UrlResource.Cl

  • Springboot工具类StringUtils使用教程

    目录 org.springframework.util.StringUtils 字符串操作 在实际的业务开发中,除了经常有针对对象的判断或操作以外,经常也会遇到的就是字符串的判断和操作.比如判断字符串是否为空.是否以某个字符结尾.去除头部和尾部的空白字符.字符的查找和替换.在Spring的核心包中存在这样一个类org.springframework.util.StringUtils,它提供了常见的关于字符串的判断和操作的静态方法.下面咱们针对一些常见的一块学习一下,顺便再把前面说的断言给复习一下

  • hutool 工具类基本使用教程

    在之前没有接触到这个工具类的时候,感觉自己好像根本就不知道这个的存在,再次之前没有一个完善的知识体系,但是在发现这个工具类之后,才真的发现这个工具类是真的好用,下面我就简单的介绍一下关于这个工具类的使用,主要参考的是这几个博客 hutool官方文档 我们下载:https://www.jb51.net/softs/549331.html 简单介绍: 博主这边的一个简单介绍 https://www.jb51.net/article/230880.htm Hutool 常用的一些方法简介: 简介 Hu

  • android自动生成dimens适配文件的图文教程详解(无需Java工具类)

    在编写ui界面时因为手机分辨率大小不同,所以展现出来的效果也是不同的,这个时候就需要考虑适配器,让根据手机分辨率自动适配相应尺寸来展示界面,可以提高用户的体验感. 1.首先安装插件ScreenMatch,安装成功之后android studio会提示重启 2.在res->values下创建一个dimens文件,将以下代码复制进去.如果不创建这个文件一下操作会不成功导致项目重启. <dimen name="common_margin">@dimen/dp_15</

  • SpringBoot整合Jackson超详细用法(附Jackson工具类)

    目录 一.Jackson简介 二.Json简介 三.springboot整合Jackson 1.创建项目 2.导入坐标 3.配置文件 4.实体类 5.测试类 一.Jackson简介 说明:本篇讲的是Jackson的详细用法,Jackson工具类在文章最后,直接复制粘贴即可使用. Jackson是公司中必用的组件之一,常用的还用阿里的Fastjson,但是由于一些原因bug与漏洞是在是太多,在注重安全的公司直接被pass,还有就是谷歌的Gson(这个没用过不太了解). Spring MVC 的默认

  • springboot封装JsonUtil,CookieUtil工具类代码实例

    这篇文章主要介绍了springboot封装JsonUtil,CookieUtil工具类过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 JsonUtil public class JsonUtil { private static ObjectMapper objectMapper = new ObjectMapper(); public static String objectToString(Object object) throws

  • Springboot实现多线程注入bean的工具类操作

    场景: 使用springboot多线程,线程类无法自动注入需要的bean 解决方法: 通过工具类获取需要的bean 工具类代码: import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springfram

随机推荐