利用反射操作bean的属性和方法

Java基础

浏览数:6

2019-9-11

今天在开发中碰到这样一个场景:当请求添加项目下的目录时,传过来的是一个IndexModel,这个Model里有关于这个目录字段的详细信息,包括基础报表,实时,漏斗等信息(这些字段类型都是boolean),对应于页面上生成目录的多选框。现要将这些配置存入数据库,在数据库中存的是这个项目下的目录,比如说在页面勾选了基础报表这个选择框,就会在数据库中的menu表插入一条数据记录这个配置。这样一来,就需要对传递过来的这个IndexModel类的属性值进行判断,再决定插入数据库的信息。

    下面是IndexModel这个model的基本属性:

 1 public class IndexModel {
 2     private Boolean basic_report;  //基础报表
 3     private Boolean realtime;   //实时
 4     private Boolean event; //事件
 5     private Boolean retain;// 留存
 6     private Boolean funnel; //漏斗
 7     private Boolean explore; //探索
 8     private Boolean grouping; //分组
 9     private Boolean user_portrait; //用户画像
10     private Boolean log; //日志
11 
12     //setters and getters ..
13 }

当某个属性为true时,则就会将这个属性配置进数据库,当这个属性为false时,则不会进行任何操作。

由此,我想到了利用Java反射,遍历这个类的属性,然后获取到这个属性的名字和值判断,再映射成数据库表的字段,插入到数据库中去。

 我们先上解决方案代码:

 1  Field[] fields = IndexModel.class.getDeclaredFields();
 2             for (int i = 0; i < fields.length; i++) {
 3                     Field f = fields[i];
 4                     f.setAccessible(true); // 设置这些属性是可以访问的
 5                     try {
 6                        if(f.getGenericType().toString().endsWith("Boolean") && (Boolean) f.get(indexModel) == true) { // 得到此属性的值
 7                             IndexDto indexDto = parseIndexModelToDto(indexModel, f.getName());
 8                             projectService.addIndex(indexDto);
 9                         }
10                     } catch (IllegalAccessException e) {
11                         logger.error("属性类型转换异常");
12                     }
13                 }

在代码中先是利用反射获取类的所有对象成员的字段值,在这里由于IndexModel中的属性字段值都是private的,所以,只能使用 getDeclaredFields()获取到这些字段,至于getFields()方法,只能获取到类(及其父类)中的公有成员,这两个方法返回的都是Field类型的数组。

在获取私有成员值之前,必须调用setAccessible(true),否则的话,将会抛出异常:java.lang.IllegalAccessException:  class… can not access ,显示不能获取字段值。

另外,在需要获取成员的类型时,需要调用相应的field的getType()方法,获取field的类型有如下几种方法

1  Class<?> type = field.getType();        // 通过这种方式只对普通类型的Field有效,如果该Field的类型是有泛型限制的类型,如Map<String,Integer>类型,则不能准确得到该Field的泛型参数。
2 
3  Type type = field.getGenericType();  // 为了获得指定Field的泛型类型,应该使用这个方法来获取指定Field的泛型类型

如果要获取上面对应field的被泛型限制的方法,就需要将上面的type对象强制类型转换成ParameterizedType对象,ParameterizedType代表被参数化的类型,也就是增加了泛型限制的类型,ParameterizedType类提供了两个方法:

    getRawType();                            返回被泛型限制的类型;

    getActualTypeArguments();        返回泛型参数类型。   

然后,要获取成员变量的名称直接使用field.getName(),但是属性值则是field.get(Object),这个object是该field所属的!

最后,要是想为这个成员变量设置值,则需要调用set:field[i].set(indexModel , true);

作者:jy的blog