1. 程式人生 > >利用反射操作bean的屬性和方法

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

兩個 決定 dto epo cts 強制 多選 通過 報表

今天在開發中碰到這樣一個場景:當請求添加項目下的目錄時,傳過來的是一個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);

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