Java通過反射注解賦值的方法詳解
前段時間,領(lǐng)導(dǎo)分配一個統(tǒng)計銷售區(qū)域匯總的數(shù)據(jù),解決方案使用到了反射獲取注解,通過注解獲取屬性或者設(shè)置字段屬性。
問題描述
查詢公司列表,分別是公司id、區(qū)域id、區(qū)域名稱:
| 公司id | 區(qū)域id | 區(qū)域名稱 |
|---|---|---|
| 1 | 1 | 華南 |
| 2 | 2 | 華北 |
| 3 | 2 | 華北 |
| 4 | 3 | 華東 |
| 5 | 3 | 華東 |
創(chuàng)建公司類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;
/**
* 區(qū)域id
*/
private Integer areaId;
/**
* 區(qū)域名稱
*/
private String areaName;
// 省略get/set方法
}
最終解決
要求匯總各個區(qū)域公司數(shù)量,得到如下匯總:
| 區(qū)域id | 區(qū)域名稱 | 公司總數(shù) |
|---|---|---|
| 1 | 華南 | 1 |
| 2 | 華北 | 2 |
| 3 | 華東 | 2 |
最終區(qū)域?qū)嶓wAreaStatistic:
public class AreaStatistic {
@ColumnProperty("華東大區(qū)")
private Integer eastChina = 0;
@ColumnProperty("華東id")
private Integer eastChinaId;
@ColumnProperty("華南大區(qū)")
private Integer southChina = 0;
@ColumnProperty("華南id")
private Integer southChinaId;
@ColumnProperty("華北大區(qū)")
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
這種做法的缺點(diǎn):
- 要寫大量的條件判斷語句,非常的繁瑣。
- 增加和減少統(tǒng)計區(qū)域,都要修改代碼。
針對上面的缺點(diǎn),使用反射獲取注解,通過注解獲取屬性賦值。
通過反射注解賦值屬性
解題思路
1.遍歷公司列表,獲取到區(qū)域id和區(qū)域名稱。
2.創(chuàng)建自定義注解@ColumnProperty:
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ColumnProperty {
String value() default "";
}
3.通過反射獲取屬性,然后遍歷字段屬性獲取注解。
在AreaStatistic字段屬性上添加注解:
@ColumnProperty("華東大區(qū)")
private Integer eastChina = 0;
@ColumnProperty("華東id")
private Integer eastChinaId;
@ColumnProperty("華南大區(qū)")
private Integer southChina = 0;
@ColumnProperty("華南id")
private Integer southChinaId;
@ColumnProperty("華北大區(qū)")
private Integer northChina = 0;
@ColumnProperty("華北id")
private Integer northChinaId;
4.通過反射獲取屬性,然后遍歷字段屬性獲取注解。
Class staticClass = areaStatistic.getClass();
Field[] fields = staticClass.getDeclaredFields();
for (Field field : fields) {
ColumnProperty property = field.getAnnotation(ColumnProperty.class);
String value = property.value();
}
5.匹配區(qū)域名稱和字段屬性,比如遍歷公司區(qū)域是華東,就遍歷到華東大區(qū)注解對應(yīng)的字段,并賦值或者獲取字段值。
if (value != null) {
int indexOf = value.indexOf("大區(qū)");
if (indexOf != -1 && value.length() == 4) {
if (areaName.equals(value.substring(0,2))) {
field.setAccessible(true);
field.set(areaStatistic,(Integer) field.get(areaStatistic) + 1);
}
}
}
6.區(qū)域id賦值也是相同的解題思路。
根據(jù)上面的思路,有如下代碼匯總:
// 遍歷公司
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("大區(qū)");
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
匯總某些字段的和
上面算出各個區(qū)域的匯總之后,還要算出全部區(qū)域的總和,這里還是使用到注解,把屬性字段包含大區(qū)都累加起來:
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("大區(qū)") != -1) {
field.setAccessible(true);
sum += field.get(statistic) == null ? 0 : (Integer) field.get(statistic);
}
}
System.out.println(sum);
輸出結(jié)果:
6
總結(jié)
1.自定義注解,通過反射獲取注解
2.通過匹配注解值,獲取或者復(fù)制對應(yīng)的字段屬性。
賦值主要代碼為:
field.setAccessible(true); field.set(Model,value);
源碼
package reflect;
import org.junit.Test;
import reflect.annotation.ColumnProperty;
import reflect.model.AreaStatistic;
import reflect.model.Company;
import javax.print.DocFlavor;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
/**
* @Author: laizc
* @Date: created in 2022-07-21
* @desc: 通過注解設(shè)值
*/
public class SetValueByAnnotation {
/**
* 通過屬性賦值
*/
@Test
public void test() throws IllegalAccessException {
// 添加數(shù)據(jù)
Company company5 = new Company(1,1,"華南");
Company company1 = new Company(2,2,"華北");
Company company2 = new Company(3,2,"華北");
Company company3 = new Company(4,3,"華東");
Company company4 = new Company(5,3,"華東");
List<Company> companyList = new ArrayList<>();
companyList.add(company5);
companyList.add(company1);
companyList.add(company2);
companyList.add(company3);
companyList.add(company4);
// 解法1
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());
}
}
System.out.println(areaStatistic);
// 解法二
AreaStatistic areaStatistic2 = new AreaStatistic();
for (Company company:companyList) {
setAreaProperty(areaStatistic2,company.getAreaName(),company.getAreaId());
}
System.out.println(areaStatistic2);
}
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("大區(qū)");
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;
}
}
}
}
}
/**
* 根據(jù)注解累加字段值
*/
@Test
public void accumulate() throws IllegalAccessException {
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("大區(qū)") != -1) {
field.setAccessible(true);
sum += field.get(statistic) == null ? 0 : (Integer) field.get(statistic);
}
}
System.out.println(sum);
}
}到此這篇關(guān)于Java通過反射注解賦值的方法詳解的文章就介紹到這了,更多相關(guān)Java反射注解賦值內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
最全JVM調(diào)優(yōu)步驟和參數(shù)及配置
這篇文章主要給大家介紹了關(guān)于JVM調(diào)優(yōu)的相關(guān)資料,JVM調(diào)優(yōu)是指對Java虛擬機(jī)(JVM)進(jìn)行優(yōu)化,以提高Java程序的性能和運(yùn)行效率,文中介紹的非常詳細(xì),需要的朋友可以參考下2024-03-03
Spring MVC全局異常處理和單元測試_動力節(jié)點(diǎn)Java學(xué)院整理
本篇文章主要介紹了Spring MVC全局異常處理和單元測試,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-08-08
springboot多環(huán)境進(jìn)行動態(tài)配置的方法
這篇文章主要介紹了springboot多環(huán)境下如何進(jìn)行動態(tài)配置,本文主要分享了如何在springboot的項目中使用多環(huán)境配置,重點(diǎn)是”spring.profiles.active“屬性,需要的朋友可以參考下2022-06-06
詳解如何在Spring中為@Value注解設(shè)置默認(rèn)值
在Spring開發(fā)中,我們經(jīng)常會遇到需要從配置文件中讀取屬性的情況,@Value注解是Spring提供的一種便捷方式,能夠讓我們輕松地將配置文件中的屬性注入到Spring Bean中,2024-10-10
Spring運(yùn)行環(huán)境Environment的解析
本文主要介紹了Spring運(yùn)行環(huán)境Environment的解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-08-08
防止SpringMVC攔截器攔截js等靜態(tài)資源文件的解決方法
本篇文章主要介紹了防止SpringMVC攔截器攔截js等靜態(tài)資源文件的解決方法,具有一定的參考價值,有興趣的同學(xué)可以了解一下2017-09-09

