最近,項(xiàng)目組要用到一個(gè)功能,就是用BeanUtils.copyProperties復(fù)制一個(gè)Map里的屬性值到另外一個(gè)對(duì)象。
BeanUtils和PropertyUtils類(lèi)是許多開(kāi)源框架中頻繁使用的兩個(gè)工具,它們都能實(shí)現(xiàn)將一個(gè)類(lèi)中的屬性拷貝到另一個(gè)類(lèi)中,這個(gè)功能甚至是spring實(shí)現(xiàn)依賴(lài)注入的基礎(chǔ)。研究一下apache的comon包中如何實(shí)現(xiàn)這個(gè)兩個(gè)工具,可以發(fā)現(xiàn)它們都是使用java.lang.reflect和java.beans這兩個(gè)包下的幾個(gè)類(lèi)來(lái)實(shí)現(xiàn)的。
但是BeanUtils.copyProperties只支持兩個(gè)對(duì)象之間的復(fù)制,其原理:是利用反射讀取到第一個(gè)對(duì)象(源類(lèi))的所有屬性,然后對(duì)這些屬性集合進(jìn)行for循環(huán),再在for循環(huán)里面判斷這些屬性是否有set方法,有則再對(duì)第二個(gè)對(duì)象(目標(biāo)類(lèi))進(jìn)行循環(huán)取出屬性一一對(duì)比,相等則調(diào)用目標(biāo)類(lèi)的set方法得到源類(lèi)的get方法得到的值。
改后主要就是兩點(diǎn):第一:源類(lèi)(Map類(lèi)型)的Key作為屬性和目標(biāo)類(lèi)的屬性對(duì)比,相等則取出此Key的Value賦給目標(biāo)類(lèi)(當(dāng)然還是用目標(biāo)類(lèi)此屬性的set方法)。注意:如果是頁(yè)面得到的getParameterMap()這樣的Map,其值是一個(gè)數(shù)組,一般只需要取第0項(xiàng)就可以了。
源代碼:
- /** 實(shí)現(xiàn)將源類(lèi)屬性拷貝到目標(biāo)類(lèi)中
- * @param source
- * @param target
- */
- public static void copyProperties(Object source, Object target) {
- try {
- // 獲取目標(biāo)類(lèi)的屬性信息
- BeanInfo targetbean = Introspector.getBeanInfo(target.getClass());
- PropertyDescriptor[] propertyDescriptors = targetbean
- .getPropertyDescriptors();
- // 對(duì)每個(gè)目標(biāo)類(lèi)的屬性查找set方法,并進(jìn)行處理
- for (int i = 0; i < propertyDescriptors.length; i++) {
- PropertyDescriptor pro = propertyDescriptors[i];
- Method wm = pro.getWriteMethod();
- if (wm != null) {// 當(dāng)目標(biāo)類(lèi)的屬性具有set方法時(shí),查找源類(lèi)中是否有相同屬性的get方法
- BeanInfo sourceBean = Introspector.getBeanInfo(source.getClass());
- PropertyDescriptor[] sourcepds = sourceBean.getPropertyDescriptors();
- for (int j = 0; j < sourcepds.length; j++) {
- if (sourcepds[j].getName().equals(pro.getName())) { // 匹配
- Method rm = sourcepds[j].getReadMethod();
- // 如果方法不可訪問(wèn)(get方法是私有的或不可達(dá)),則拋出SecurityException
- if (!Modifier.isPublic(rm.getDeclaringClass().getModifiers())) {
- rm.setAccessible(true);
- }
- // 獲取對(duì)應(yīng)屬性get所得到的值
- Object value = rm.invoke(source, new Object[0]);
- if (!Modifier.isPublic(wm.getDeclaringClass().getModifiers())) {
- wm.setAccessible(true);
- }
- // 調(diào)用目標(biāo)類(lèi)對(duì)應(yīng)屬性的set方法對(duì)該屬性進(jìn)行填充
- wm.invoke((Object) target, new Object[] { value });
- break;
- }
- }
- }
- }
- } catch (IntrospectionException e) {
- e.printStackTrace();
- } catch (IllegalArgumentException e) {
- e.printStackTrace();
- } catch (IllegalAccessException e) {
- e.printStackTrace();
- } catch (InvocationTargetException e) {
- e.printStackTrace();
- }
- }
修改后支持Map的代碼:
- /**
- * 實(shí)現(xiàn)將源類(lèi)屬性拷貝到目標(biāo)類(lèi)中
- *
- * @param Map map
- * @param Object obj
- */
- public static void copyProperties(Map map, Object obj) throws Exception {
- // 獲取目標(biāo)類(lèi)的屬性信息
- BeanInfo targetbean = Introspector.getBeanInfo(obj.getClass());
- PropertyDescriptor[] propertyDescriptors = targetbean.getPropertyDescriptors();
- // 對(duì)每個(gè)目標(biāo)類(lèi)的屬性查找set方法,并進(jìn)行處理
- for (int i = 0; i < propertyDescriptors.length; i++) {
- PropertyDescriptor pro = propertyDescriptors[i];
- Method wm = pro.getWriteMethod();
- if (wm != null) {// 當(dāng)目標(biāo)類(lèi)的屬性具有set方法時(shí),查找源類(lèi)中是否有相同屬性的get方法
- Iterator ite = map.keySet().iterator();
- while (ite.hasNext()) {
- String key = (String) ite.next();
- // 判斷匹配
- if (key.equals(pro.getName())) {
- if (!Modifier.isPublic(wm.getDeclaringClass().getModifiers())) {
- wm.setAccessible(true);
- }
- Object value = ((String[]) map.get(key))[0];
- // 調(diào)用目標(biāo)類(lèi)對(duì)應(yīng)屬性的set方法對(duì)該屬性進(jìn)行填充
- wm.invoke((Object) obj, new Object[] { value });
- break;
- }
- }
- }
- }
- }
上次寫(xiě)的那個(gè)方法只適用于String類(lèi)型。今天擴(kuò)展了一下,寫(xiě)成了一個(gè)類(lèi),支持int/Integer、Date和自定義對(duì)象。
- import java.beans.BeanInfo;
- import java.beans.Introspector;
- import java.beans.PropertyDescriptor;
- import java.lang.reflect.InvocationTargetException;
- import java.lang.reflect.Method;
- import java.lang.reflect.Modifier;
- import java.text.ParseException;
- import java.text.SimpleDateFormat;
- import java.util.Date;
- import java.util.Iterator;
- import java.util.Map;
- public class BeanUtils {
- public static String DATE_FORMAT = "yyyy-MM-dd";
- public static String[] TYPE_SIMPLE = {"java.lang.Integer","int","java.util.Date"};
- public static String TYPE_INTEGER = "java.lang.Integer,int";
- public static String TYPE_DATE = "java.util.Date";
-
- /**
- * 得到空格之后的字符
- *
- * @param String type
- * @param String str
- * @return Date
- * @throws ParseException
- */
- public static String splitSpace(String str) throws ParseException{
- if(str.contains(" ")){
- return str.split(" ")[1];
- } else {
- return str;
- }
- }
-
- /**
- * 判斷是否是簡(jiǎn)單數(shù)據(jù)類(lèi)型
- *
- * @param String type
- */
- public static boolean isSimpleType(String type) {
- for (int i = 0; i < TYPE_SIMPLE.length; i++) {
- if (type.equals(TYPE_SIMPLE[i])) {
- return true;
- }
- }
- return false;
- }
- /**
- * 把String類(lèi)型轉(zhuǎn)換為Integer
- *
- * @param String str
- * @return Integer
- */
- public static Integer parseInteger(String str){
- if(str == null || str.equals("")){
- return 0;
- } else {
- return Integer.parseInt(str);
- }
- }
-
- /**
- * 把String類(lèi)型轉(zhuǎn)換為Date
- *
- * @param String str
- * @return Date
- * @throws ParseException
- */
- public static Date parseDate(String str) throws ParseException{
- if(str == null || str.equals("")){
- return null;
- } else {
- SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
- Date date = sdf.parse(str);
- return date;
- }
- }
-
- /**
- * 轉(zhuǎn)換對(duì)象(用戶定義的對(duì)象)。設(shè)置對(duì)象的Id。
- *
- * @param Class clazz
- * @param String str
- * @return Object
- * @throws IllegalAccessException
- * @throws InstantiationException
- * @throws NoSuchMethodException
- * @throws SecurityException
- * @throws InvocationTargetException
- * @throws IllegalArgumentException
- * @throws ParseException
- */
- public static Object parseObject(Class clazz, String str) throws InstantiationException, IllegalAccessException, SecurityException, NoSuchMethodException, IllegalArgumentException, InvocationTargetException {
- Object obj;
- if(str == null || str.equals("")){
- obj = null;
- } else {
- obj = clazz.newInstance();
- Method m = clazz.getMethod("setId",str.getClass());
- m.invoke(obj,str);
- }
- return obj;
- }
-
- /**
- * 根據(jù)類(lèi)型進(jìn)行轉(zhuǎn)換
- *
- * @param Class clazz
- * @param String str
- * @return Object
- * @throws ParseException
- * @throws IllegalAccessException
- * @throws InstantiationException
- * @throws InvocationTargetException
- * @throws NoSuchMethodException
- * @throws IllegalArgumentException
- * @throws SecurityException
- */
- public static Object parseByType(Class clazz, String str) throws ParseException, InstantiationException, IllegalAccessException, SecurityException, IllegalArgumentException, NoSuchMethodException, InvocationTargetException{
- Object r = "";
- String clazzName = splitSpace(clazz.getName());
- if (isSimpleType(clazzName)){
- if (TYPE_INTEGER.contains(clazzName)) {
- r = parseInteger(str);
- } else if (TYPE_DATE.contains(clazzName)) {
- r = parseDate(str);
- }
- } else {
- r = parseObject(clazz, str);
- }
- return r;
- }
-
- /** 實(shí)現(xiàn)將源類(lèi)(Map類(lèi)型)屬性拷貝到目標(biāo)類(lèi)中
- * @param Map map
- * @param Object obj
- */
- public static void copyProperties(Map map, Object obj) throws Exception {
- // 獲取目標(biāo)類(lèi)的屬性信息
- BeanInfo targetbean = Introspector.getBeanInfo(obj.getClass());
- PropertyDescriptor[] propertyDescriptors = targetbean.getPropertyDescriptors();
- // 對(duì)每個(gè)目標(biāo)類(lèi)的屬性查找set方法,并進(jìn)行處理
- for (int i = 0; i < propertyDescriptors.length; i++) {
- PropertyDescriptor pro = propertyDescriptors[i];
- Method wm = pro.getWriteMethod();
- if (wm != null) {
- Iterator ite = map.keySet().iterator();
- while (ite.hasNext()) {
- String key = (String) ite.next();
- // 判斷匹配
- if (key.toLowerCase().equals(pro.getName().toLowerCase())) {
- if (!Modifier.isPublic(wm.getDeclaringClass().getModifiers())) {
- wm.setAccessible(true);
- }
- Object value = ((String[]) map.get(key))[0];
- String pt = splitSpace(pro.getPropertyType().getName());
- //判斷類(lèi)型是否匹配,不匹配則作強(qiáng)制轉(zhuǎn)換
- if (!(pt.equals(value.getClass().getName()))) {
- value = parseByType(pro.getPropertyType(),value.toString());
- }
- // 調(diào)用目標(biāo)類(lèi)對(duì)應(yīng)屬性的set方法對(duì)該屬性進(jìn)行填充
- wm.invoke((Object) obj, new Object[] {value});
- break;
- }
- }
- }
- }
- }
- }
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)
點(diǎn)擊舉報(bào)。