前段時間,領導分配一個統計銷售區域彙總的資料,解決方案使用到了反射獲取註解,通過註解獲取屬性或者設定欄位屬性。
查詢公司列表,分別是公司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方法
}
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
這種做法的缺點:
針對上面的缺點,使用反射獲取註解,通過註解獲取屬性賦值。
@ColumnProperty
:@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ColumnProperty {
String value() default "";
}
在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;
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 (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);