Springboot工具类ReflectionUtils使用教程

 更新时间:2022年12月30日 10:58:46   作者:凡夫贩夫  
这篇文章主要介绍了Springboot内置的工具类之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内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java拖曳鼠标实现画线功能的方法

    Java拖曳鼠标实现画线功能的方法

    这篇文章主要介绍了Java拖曳鼠标实现画线功能的方法,需要的朋友可以参考下
    2014-07-07
  • 如何使用jenkins实现发布部分更新文件

    如何使用jenkins实现发布部分更新文件

    这篇文章主要介绍了如何使用jenkins实现发布部分更新文件,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-07-07
  • Mybatis-plus foreach拼接字符串查询无数据返回问题

    Mybatis-plus foreach拼接字符串查询无数据返回问题

    这篇文章主要介绍了Mybatis-plus foreach拼接字符串查询无数据返回问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-03-03
  • Java实现的两个线程同时运行案例

    Java实现的两个线程同时运行案例

    这篇文章主要介绍了Java实现的两个线程同时运行,涉及java多线程相关操作与使用技巧,需要的朋友可以参考下
    2019-07-07
  • java中将科学计数法转换普通计数法的简单方法

    java中将科学计数法转换普通计数法的简单方法

    下面小编就为大家带来一篇java中将科学计数法转换普通计数法的简单方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-12-12
  • 使用spring data的page和pageable如何实现分页查询

    使用spring data的page和pageable如何实现分页查询

    这篇文章主要介绍了使用spring data的page和pageable如何实现分页查询,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-12-12
  • Spring设计模式中代理模式详细讲解

    Spring设计模式中代理模式详细讲解

    如何实现在不修改源码的基础上实现代码功能的增强呢?spring为我们提供了代理模式。所谓的代理模式通俗来说就是一个中介,它给某一个对象提供一个代理对象,并由代理对象控制原对象的引用,从而实现在不修改源码的基础上实现代码功能的增强
    2023-01-01
  • Java面向对象程序设计:抽象类,接口用法实例分析

    Java面向对象程序设计:抽象类,接口用法实例分析

    这篇文章主要介绍了Java面向对象程序设计:抽象类,接口用法,结合实例形式分析了java抽象类与接口相关概念、原理、用法与操作注意事项,需要的朋友可以参考下
    2020-04-04
  • java实现文件和base64相互转换

    java实现文件和base64相互转换

    这篇文章主要为大家详细介绍了java如何实现文件和base64相互转换,文中的示例代码讲解详细,具有一定的参考价值,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-11-11
  • Java基础之如何学好Java

    Java基础之如何学好Java

    这篇文章已经是有数年“网龄”的老文,不过在今天看来仍然经典。如何学习java?本篇文章可以说也是面对编程初学者的一篇指导文章,其中对于如何学习Java的步骤的介绍,很多也适用于开发领域其他技能的学习。
    2014-10-10

最新评论