关于java:Java通过反射注解赋值

31次阅读

共计 4356 个字符,预计需要花费 11 分钟才能阅读完成。

前段时间,领导调配一个统计销售区域汇总的数据,解决方案应用到了反射获取注解,通过注解获取属性或者设置字段属性。

问题形容

查问公司列表,别离是公司 id、区域 id、区域名称:

公司 id 区域 id 区域名称
1 1 华南
2 2 华北
3 2 华北
4 3 华东
5 3 华东

创立公司类Company

public class Company {public Company(Integer id,  Integer areaId, String areaName) {
        this.id = id;
        this.areaId = areaId;
        this.areaName = areaName;
    }

    /**
     * 公司 id
     */
    private Integer id;

    /**
     * 区域 id
     */
    private Integer areaId;

    /**
     * 区域名称
     */
    private String areaName;
     
    // 省略 get/set 办法 

}

最终解决

要求 汇总 各个区域公司数量, 失去如下汇总:

区域 id 区域名称 公司总数
1 华南 1
2 华北 2
3 华东 2

最终区域实体AreaStatistic:

public class AreaStatistic {@ColumnProperty("华东大区")
    private Integer eastChina = 0;

    @ColumnProperty("华东 id")
    private Integer eastChinaId;

    @ColumnProperty("华南大区")
    private Integer southChina = 0;

    @ColumnProperty("华南 id")
    private Integer southChinaId;

    @ColumnProperty("华北大区")
    private Integer northChina = 0;

    @ColumnProperty("华北 id")
    private Integer northChinaId;

    @Override
    public String toString() {
        return "AreaStatistic{\n" +
                "华东 Id=" + eastChinaId +
                ", 华东 =" + eastChina +
                ", \n 华南 Id=" + southChinaId +
                ", 华南 =" + southChina +
                ", \n 华北 Id=" + northChinaId +
                ", 华北 =" + northChina +
                '}';
    }
    // 省略 get/set 办法
}

if/else 一般解法

AreaStatistic areaStatistic = new AreaStatistic();
for (Company company:companyList) {String areaName = company.getAreaName();
    if ("华南".equals(areaName)) {areaStatistic.setSouthChina(areaStatistic.getSouthChina()+1);
        areaStatistic.setSouthChinaId(company.getAreaId());
    } else if ("华北".equals(areaName)) {areaStatistic.setNorthChina(areaStatistic.getNorthChina()+1);
        areaStatistic.setNorthChinaId(company.getAreaId());
    } else if ("华东".equals(areaName)) {areaStatistic.setEastChina(areaStatistic.getEastChina()+1);
        areaStatistic.setEastChinaId(company.getAreaId());
    }
}

输入:

华东 Id=3, 华东 =2, 
华南 Id=1, 华南 =1, 
华北 Id=2, 华北 =2

这种做法的毛病:

  • 要写大量的条件判断语句,十分的繁琐。
  • 减少和缩小统计区域,都要批改代码。

针对下面的毛病,应用反射获取注解,通过注解获取属性赋值。

通过反射注解赋值属性

解题思路

  1. 遍历公司列表,获取到区域 id 和区域名称。
  2. 创立自定义注解@ColumnProperty:
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ColumnProperty {String value() default "";

}
  1. 通过反射获取属性,而后遍历字段属性获取注解。

AreaStatistic 字段属性上增加注解:

@ColumnProperty("华东大区")
private Integer eastChina = 0;

@ColumnProperty("华东 id")
private Integer eastChinaId;

@ColumnProperty("华南大区")
private Integer southChina = 0;

@ColumnProperty("华南 id")
private Integer southChinaId;

@ColumnProperty("华北大区")
private Integer northChina = 0;

@ColumnProperty("华北 id")
private Integer northChinaId;
  1. 通过反射获取属性,而后遍历字段属性获取注解。
Class staticClass = areaStatistic.getClass();
Field[] fields = staticClass.getDeclaredFields();
for (Field field : fields) {ColumnProperty property = field.getAnnotation(ColumnProperty.class);
    String value = property.value();}
  1. 匹配区域名称和字段属性,比方遍历公司区域是 华东 ,就遍历到 华东大区 注解对应的字段,并赋值或者获取字段值。
if (value != null) {int indexOf = value.indexOf("大区");
    if (indexOf != -1 && value.length() == 4) {if (areaName.equals(value.substring(0,2))) {field.setAccessible(true);
            field.set(areaStatistic,(Integer) field.get(areaStatistic) + 1);  
        }
     }
}
  1. 区域 id 赋值也是雷同的解题思路。

依据下面的思路,有如下 代码汇总

// 遍历公司
for (Company company:companyList) {setAreaProperty(areaStatistic2,company.getAreaName(),company.getAreaId());
}

private void setAreaProperty(AreaStatistic areaStatistic,String areaName,Integer areaId) throws IllegalAccessException {
    // 反射获取注解 
    Class staticClass = areaStatistic.getClass();
    Field[] fields = staticClass.getDeclaredFields();
    for (Field field : fields) {ColumnProperty property = field.getAnnotation(ColumnProperty.class);
        String value = property.value();
        if (value != null) {int indexOf = value.indexOf("大区");
            if (indexOf != -1 && value.length() == 4) {
                // 匹配到注解属性并赋值 
                if (areaName.equals(value.substring(0,2))) {field.setAccessible(true);
                    field.set(areaStatistic,(Integer) field.get(areaStatistic) + 1);
                    for (Field idField : fields) {ColumnProperty idProperty = idField.getAnnotation(ColumnProperty.class);
                        String idValue = idProperty.value();
                        if (idValue.equals(areaName+"id")) {idField.setAccessible(true);
                            idField.set(areaStatistic,areaId);
                            break;
                        }
                    }
                    break;
                }
            }
        }
    }
}

输入:

华东 Id=3, 华东 =2, 
华南 Id=1, 华南 =1, 
华北 Id=2, 华北 =2

汇总某些字段的和

下面算出各个区域的汇总之后,还要算出全副区域的总和,这里还是应用到注解,把属性字段蕴含 大区 都累加起来:

AreaStatistic statistic = new AreaStatistic();
statistic.setEastChina(2);
statistic.setNorthChina(3);
statistic.setSouthChina(1);
int sum = 0;
Class staticClass = statistic.getClass();
Field[] fields = staticClass.getDeclaredFields();
for (Field field : fields) {ColumnProperty property = field.getAnnotation(ColumnProperty.class);
    String value = property.value();
    if (value.indexOf("大区") != -1) {field.setAccessible(true);
        sum += field.get(statistic) == null ? 0 : (Integer) field.get(statistic);
    }
}
System.out.println(sum);

输入后果:

6

总结

  • 自定义注解,通过反射获取注解
  • 通过匹配注解值,获取或者复制对应的字段属性。

赋值次要代码为:

field.setAccessible(true);
field.set(Model,value);

源码地址

https://github.com/jeremylai7/java-codes/blob/master/basis/src/main/java/reflect/SetValueByAnnotation.java

正文完
 0