BeanUtils.java 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620
  1. package com.behosoft.util;
  2. import java.beans.PropertyDescriptor;
  3. import java.io.PrintStream;
  4. import java.lang.reflect.Field;
  5. import java.lang.reflect.InvocationTargetException;
  6. import java.lang.reflect.Method;
  7. import java.lang.reflect.ParameterizedType;
  8. import java.lang.reflect.Type;
  9. import java.lang.reflect.TypeVariable;
  10. import java.text.SimpleDateFormat;
  11. import java.util.Date;
  12. import java.util.HashMap;
  13. import java.util.Map;
  14. import java.util.Set;
  15. import org.apache.commons.beanutils.BeanUtilsBean;
  16. import org.apache.commons.beanutils.DynaBean;
  17. import org.apache.commons.beanutils.MethodUtils;
  18. import org.apache.commons.beanutils.NestedNullException;
  19. import org.apache.commons.beanutils.PropertyUtils;
  20. import com.behosoft.framework.web.model.RecordBO;
  21. /**
  22. * <pre></pre>
  23. *
  24. * <br>
  25. * JDK版本:1.6
  26. *
  27. * @author 刘俊杰
  28. * @version 1.0
  29. * @see The author for more details
  30. * @since 1.0
  31. */
  32. public class BeanUtils {
  33. public static Object getStaticProperty(Class clazz, String name) {
  34. try {
  35. return clazz.getField(name).get(null);
  36. } catch (IllegalArgumentException e) {
  37. throw new BeanAccessException("在读取类[" + clazz + "]的静态属性[" + name
  38. + "]时遇到错误", e);
  39. } catch (SecurityException e) {
  40. throw new BeanAccessException("在读取类[" + clazz + "]的静态属性[" + name
  41. + "]时遇到错误", e);
  42. } catch (IllegalAccessException e) {
  43. throw new BeanAccessException("在读取类[" + clazz + "]的静态属性[" + name
  44. + "]时遇到错误", e);
  45. } catch (NoSuchFieldException e) {
  46. throw new BeanAccessException("在读取类[" + clazz + "]的静态属性[" + name
  47. + "]时遇到错误", e);
  48. }
  49. }
  50. public static Object getProperty(Object bean, String name) {
  51. try {
  52. return PropertyUtils.getProperty(bean, name);
  53. } catch (NestedNullException e) {
  54. return null;
  55. } catch (IllegalAccessException e) {
  56. throw new BeanAccessException("在读取bean[" + bean + "]的属性[" + name
  57. + "]时遇到错误", e);
  58. } catch (InvocationTargetException e) {
  59. throw new BeanAccessException("在读取bean[" + bean + "]的属性[" + name
  60. + "]时遇到错误", e);
  61. } catch (NoSuchMethodException e) {
  62. throw new BeanAccessException("在读取bean[" + bean + "]的属性[" + name
  63. + "]时遇到错误", e);
  64. }
  65. }
  66. public static void setProperty(Object bean, String name, Object value) {
  67. try {
  68. PropertyUtils.setProperty(bean, name, value);
  69. } catch (IllegalAccessException e) {
  70. throw new BeanAccessException("在将属性[" + name + "]写入bean[" + bean
  71. + "]时遇到错误", e);
  72. } catch (InvocationTargetException e) {
  73. throw new BeanAccessException("在将属性[" + name + "]写入bean[" + bean
  74. + "]时遇到错误", e);
  75. } catch (NoSuchMethodException e) {
  76. throw new BeanAccessException("在将属性[" + name + "]写入bean[" + bean
  77. + "]时遇到错误", e);
  78. }
  79. }
  80. public static void setSimpleProperty(Object bean, String name, Object value) {
  81. try {
  82. PropertyUtils.setSimpleProperty(bean, name, value);
  83. } catch (IllegalAccessException e) {
  84. throw new BeanAccessException("在将属性[" + name + "]写入bean[" + bean
  85. + "]时遇到错误", e);
  86. } catch (InvocationTargetException e) {
  87. throw new BeanAccessException("在将属性[" + name + "]写入bean[" + bean
  88. + "]时遇到错误", e);
  89. } catch (NoSuchMethodException e) {
  90. throw new BeanAccessException("在将属性[" + name + "]写入bean[" + bean
  91. + "]时遇到错误", e);
  92. }
  93. }
  94. /**
  95. * 获取bean的指定名称的属性,如果不存在指定的属性,返回null
  96. *
  97. * @param bean
  98. * @param name
  99. * @return
  100. */
  101. public static Object getPropertyIf(Object bean, String name) {
  102. if (hasProperty(bean, name)) {
  103. return getProperty(bean, name);
  104. } else
  105. return null;
  106. }
  107. public static Object getSimpleProperty(Object bean, String name) {
  108. try {
  109. return PropertyUtils.getSimpleProperty(bean, name);
  110. } catch (IllegalAccessException e) {
  111. throw new BeanAccessException("在读取bean[" + bean + "]的属性[" + name
  112. + "]时遇到错误", e);
  113. } catch (InvocationTargetException e) {
  114. throw new BeanAccessException("在读取bean[" + bean + "]的属性[" + name
  115. + "]时遇到错误", e);
  116. } catch (NoSuchMethodException e) {
  117. throw new BeanAccessException("在读取bean[" + bean + "]的属性[" + name
  118. + "]时遇到错误", e);
  119. }
  120. }
  121. /**
  122. * 返回bean是否有指定的属性
  123. *
  124. * @param bean
  125. * @param name
  126. * @return
  127. */
  128. public static boolean hasProperty(Object bean, String name) {
  129. if (bean == null || StringUtils.isBlank(name))
  130. return false;
  131. return getPropertyDescriptor(bean.getClass(), name) != null;
  132. }
  133. /**
  134. * 调用指定的方法
  135. *
  136. * @param object
  137. * @param methodName
  138. * @param args
  139. * 方法参数,不能用null值
  140. * @return
  141. */
  142. public static Object invokeMethod(Object object, String methodName,
  143. Object[] args, Class[] parameterTypes) {
  144. try {
  145. // 试着将参数转换成合法的参数类型
  146. if (args != null && args.length > 0 && parameterTypes != null
  147. && parameterTypes.length > 0
  148. && args.length == parameterTypes.length) {
  149. Object[] args2 = new Object[args.length];
  150. for (int i = 0; i < args.length; i++) {
  151. args2[i] = DataUtils.as(args[i], parameterTypes[i]);
  152. }
  153. args = args2;
  154. }
  155. return MethodUtils.invokeMethod(object, methodName, args,
  156. parameterTypes);
  157. } catch (NoSuchMethodException e) {
  158. throw new BeanAccessException("调用bean[" + object + "的方法["
  159. + methodName + "]时遇到一个错误", e);
  160. } catch (IllegalAccessException e) {
  161. throw new BeanAccessException("调用bean[" + object + "的方法["
  162. + methodName + "]时遇到一个错误", e);
  163. } catch (InvocationTargetException e) {
  164. throw new BeanAccessException("调用bean[" + object + "的方法["
  165. + methodName + "]时遇到一个错误", e);
  166. }
  167. }
  168. public static PropertyDescriptor getPropertyDescriptor(Class beanClass,
  169. String proName) {
  170. return org.springframework.beans.BeanUtils.getPropertyDescriptor(
  171. beanClass, proName);
  172. }
  173. public static PropertyDescriptor[] getPropertyDescriptors(Class beanClass) {
  174. return org.springframework.beans.BeanUtils
  175. .getPropertyDescriptors(beanClass);
  176. }
  177. /**
  178. * 返回一个bean的Map形式
  179. *
  180. * @param bean
  181. * @param ignoreProperties
  182. * 要忽略的属性名
  183. * @return
  184. */
  185. public static Map<String, Object> describe(Object bean,
  186. String[] ignoreProperties) {
  187. if (bean == null)
  188. return null;
  189. if (bean instanceof DynaBean) {
  190. try {
  191. return BeanUtilsBean.getInstance().describe(bean);
  192. } catch (IllegalAccessException e) {
  193. throw new BeanAccessException("在将Bean[" + bean
  194. + "]转换成Map形式时遇到一个错误:", e);
  195. } catch (InvocationTargetException e) {
  196. throw new BeanAccessException("在将Bean[" + bean
  197. + "]转换成Map形式时遇到一个错误:", e);
  198. } catch (NoSuchMethodException e) {
  199. throw new BeanAccessException("在将Bean[" + bean
  200. + "]转换成Map形式时遇到一个错误:", e);
  201. }
  202. }
  203. Map<String, Object> description = new HashMap<String, Object>();
  204. PropertyDescriptor[] descriptors = BeanUtilsBean.getInstance()
  205. .getPropertyUtils().getPropertyDescriptors(bean);
  206. Class clazz = bean.getClass();
  207. for (int i = 0; i < descriptors.length; i++) {
  208. String name = descriptors[i].getName();
  209. boolean ignore = false;
  210. if (ignoreProperties != null) {
  211. for (String ignorePro : ignoreProperties) {
  212. if (name.equals(ignorePro)) {
  213. ignore = true;
  214. break;
  215. }
  216. }
  217. }
  218. if (ignore)
  219. continue;
  220. if (MethodUtils.getAccessibleMethod(clazz,
  221. descriptors[i].getReadMethod()) != null) {
  222. description.put(name, getSimpleProperty(bean, name));
  223. }
  224. }
  225. return description;
  226. }
  227. /**
  228. * 返回一个bean的Map形式
  229. *
  230. * @param bean
  231. * @return
  232. */
  233. public static Map<String, Object> describe(Object bean) {
  234. return describe(bean, null);
  235. }
  236. public static void printBean(PrintStream ps, Object bean,
  237. String... ignoreProperties) {
  238. ps.println("start printBean:" + bean.getClass());
  239. if (bean == null) {
  240. ps.println("null");
  241. return;
  242. }
  243. Map<String, Object> map = describe(bean, ignoreProperties);
  244. for (Map.Entry<String, Object> ent : map.entrySet()) {
  245. ps.println(ent.getKey() + ": " + ent.getValue());
  246. }
  247. ps.println("end printBean:" + bean.getClass());
  248. }
  249. public static void printBean(Object bean, String... ignoreProperties) {
  250. printBean(System.out, bean, ignoreProperties);
  251. }
  252. /**
  253. * 打印两个bean不同的属性
  254. *
  255. * @param ps
  256. * @param bean1
  257. * @param bean2
  258. * @param ignoreProperties
  259. */
  260. public static void printCompareBeans(PrintStream ps, Object bean1,
  261. Object bean2, String... ignoreProperties) {
  262. ps.println("start compare " + bean1.getClass() + "," + bean2.getClass());
  263. Map<String, Object> map1 = describe(bean1, ignoreProperties);
  264. Map<String, Object> map2 = describe(bean2, ignoreProperties);
  265. Set<String> keySet1 = map1.keySet();
  266. Set<String> keySet2 = map2.keySet();
  267. for (String key : keySet1) {
  268. Object value1 = map1.get(key);
  269. Object value2 = map2.get(key);
  270. if (!equals(value1, value2)) {
  271. ps.println("key=" + key);
  272. ps.println("value1=" + value1);
  273. ps.println("value2=" + value2);
  274. }
  275. keySet2.remove(key);
  276. }
  277. for (String key : keySet2) {
  278. Object value1 = map1.get(key);
  279. Object value2 = map2.get(key);
  280. if (!equals(value1, value2)) {
  281. ps.println("key=" + key);
  282. ps.println("value1=" + value1);
  283. ps.println("value2=" + value2);
  284. }
  285. }
  286. ps.println("end compare " + bean1.getClass() + "," + bean2.getClass());
  287. }
  288. /**
  289. * 打印两个bean不同的属性
  290. *
  291. * @param bean1
  292. * @param bean2
  293. * @param ignoreProperties
  294. */
  295. public static void printCompareBeans(Object bean1, Object bean2,
  296. String... ignoreProperties) {
  297. printCompareBeans(System.out, bean1, bean2, ignoreProperties);
  298. }
  299. public static boolean equals(Object obj1, Object obj2) {
  300. if (obj1 == null) {
  301. return obj2 == null;
  302. }
  303. return obj1.equals(obj2);
  304. }
  305. /**
  306. * 返回类对于指定超类或接口实现的类型参数数组
  307. *
  308. * <pre>
  309. * 例如有如下定义:
  310. * class A<T>{}
  311. *
  312. * interface IA<T1,T2>{}
  313. *
  314. * class B extends A<String> implements IA<Double,Integer>{}
  315. *
  316. * class C<T1,T2> extends A<T1> implements IA<T2,Integer>{}
  317. *
  318. * class C2 extends C<Double,String>{}
  319. *
  320. * class D extends C{}
  321. *
  322. * getTypeArguments(B.class,A.class) 返回[String.class]
  323. * getTypeArguments(B.class,IA.class) 返回[Double.class,Integer.class]
  324. * getTypeArguments(C2.class,A.class) 返回[Double.class]
  325. * getTypeArguments(C2.class,IA.class) 返回[String.class,Integer.class]
  326. * getTypeArguments(C.class,IA.class) 返回[null,Integer.class]
  327. * getTypeArguments(D.class,C.class) 返回null
  328. * </pre>
  329. *
  330. * @param cls
  331. * @param superType
  332. * @return
  333. */
  334. @SuppressWarnings("unchecked")
  335. public static Type[] getTypeArguments(Class cls, Class superType) {
  336. if (superType.isAssignableFrom(cls))
  337. return searchTypeArguments(cls, cls, superType);
  338. else
  339. return null;
  340. }
  341. @SuppressWarnings("unchecked")
  342. private static Type[] searchTypeArguments(Class rootCls, Class cls,
  343. Class superType) {
  344. Type[] sts = getAllGenericSuperTypes(cls);
  345. for (Type st : sts) {
  346. if (superType == st) {
  347. } else if (st instanceof ParameterizedType
  348. && ((ParameterizedType) st).getRawType() == superType) {
  349. Type[] rs = ((ParameterizedType) st).getActualTypeArguments();
  350. for (int i = 0; i < rs.length; i++) {
  351. if (rs[i] instanceof TypeVariable) {
  352. rs[i] = getTypeArgumentsForTypeVariable(rootCls, cls,
  353. (TypeVariable) rs[i]);
  354. }
  355. }
  356. return rs;
  357. }
  358. }
  359. for (Type st : sts) {
  360. Type[] rs = null;
  361. if (st instanceof Class) {
  362. rs = searchTypeArguments(rootCls, (Class) st, superType);
  363. } else if (st instanceof ParameterizedType) {
  364. rs = searchTypeArguments(rootCls,
  365. (Class) (((ParameterizedType) st).getRawType()),
  366. superType);
  367. }
  368. if (rs != null)
  369. return rs;
  370. }
  371. return null;
  372. }
  373. @SuppressWarnings("unchecked")
  374. private static Type getTypeArgumentsForTypeVariable(Class cls,
  375. Class superType, TypeVariable typeVariable) {
  376. int k = -1;
  377. for (int i = 0; i < superType.getTypeParameters().length; i++) {
  378. if (typeVariable == superType.getTypeParameters()[i]) {
  379. k = i;
  380. break;
  381. }
  382. }
  383. if (k >= superType.getTypeParameters().length || k < 0) {
  384. throw new RuntimeException(typeVariable + "不是" + superType
  385. + "的类型参数变量");
  386. }
  387. return searchTypeArgumentsForTypeVariable(cls, cls, superType, k);
  388. }
  389. @SuppressWarnings("unchecked")
  390. private static Type searchTypeArgumentsForTypeVariable(Class rootCls,
  391. Class cls, Class superType, int i) {
  392. Type[] sts = getAllGenericSuperTypes(cls);
  393. for (Type st : sts) {
  394. if (superType == st) {
  395. } else if (st instanceof ParameterizedType
  396. && ((ParameterizedType) st).getRawType() == superType) {
  397. Type t = ((ParameterizedType) st).getActualTypeArguments()[i];
  398. if (t instanceof TypeVariable) {
  399. Type t2 = getTypeArgumentsForTypeVariable(rootCls, cls,
  400. (TypeVariable) t);
  401. if (t2 != null)
  402. t = t2;
  403. }
  404. return t;
  405. }
  406. }
  407. for (Type st : sts) {
  408. Type r = null;
  409. if (st instanceof Class) {
  410. r = searchTypeArgumentsForTypeVariable(rootCls, (Class) st,
  411. superType, i);
  412. } else if (st instanceof ParameterizedType) {
  413. r = searchTypeArgumentsForTypeVariable(rootCls,
  414. (Class) (((ParameterizedType) st).getRawType()),
  415. superType, i);
  416. }
  417. if (r != null)
  418. return r;
  419. }
  420. return null;
  421. }
  422. private static Type[] getAllGenericSuperTypes(Class cls) {
  423. Type[] superTypes;
  424. Type[] ts = cls.getGenericInterfaces();
  425. if (ts != null && ts.length > 0) {
  426. superTypes = new Type[ts.length + 1];
  427. System.arraycopy(ts, 0, superTypes, 1, ts.length);
  428. } else {
  429. superTypes = new Type[1];
  430. }
  431. superTypes[0] = cls.getGenericSuperclass();
  432. return superTypes;
  433. }
  434. public static boolean isSimpleValueType(Class clazz) {
  435. return org.springframework.beans.BeanUtils.isSimpleValueType(clazz);
  436. }
  437. // 测试getTypeArguments
  438. // class A<T> {
  439. // }
  440. //
  441. // interface IA<T1, T2> {
  442. // }
  443. //
  444. // class B extends A<String> implements IA<Double, Integer> {
  445. // }
  446. //
  447. // class C<T1, T2> extends A<T1> implements IA<T2, Integer> {
  448. // }
  449. //
  450. // class C2 extends C<Double, String> {
  451. // }
  452. //
  453. // class D extends C {
  454. //
  455. // }
  456. //
  457. // private static void test(Class cls, Class superCls) {
  458. // System.out.println("test:" + cls + "," + superCls);
  459. // Type[] ts = getTypeArguments(cls, superCls);
  460. // if (ts != null) {
  461. // String str = "[";
  462. // for (int i = 0; i < ts.length; i++) {
  463. // if (i > 0)
  464. // str += ",";
  465. // str += ts[i];
  466. // }
  467. // str += "]";
  468. // System.out.println(str);
  469. // }
  470. // else
  471. // System.out.println(ts);
  472. //
  473. // }
  474. //
  475. // public static void main(String[] args) {
  476. // test(B.class, A.class);
  477. // test(B.class, IA.class);
  478. // test(C2.class, A.class);
  479. // test(C2.class, IA.class);
  480. // test(C.class, IA.class);
  481. // test(IA.class, IA.class);
  482. // test(D.class, C.class);
  483. // }
  484. /**
  485. * 将一个JavaBean风格对象的属性值拷贝到另一个对象的同名属性中
  486. * (如果不存在同名属性的就不拷贝)
  487. * 本方法目前只为系统Bo转换为报文对象内部对象时的属性复制服务,其它功能请慎用。
  488. */
  489. @SuppressWarnings("unchecked")
  490. public static void copyProperties(Object target, Object source)
  491. throws Exception {
  492. /*
  493. * 分别获得源对象和目标对象的Class类型对象,Class对象是整个反射机制的源头和灵魂!
  494. *
  495. * Class对象是在类加载的时候产生,保存着类的相关属性,构造器,方法等信息
  496. */
  497. Class sourceClz = source.getClass();
  498. Class targetClz = target.getClass();
  499. // 得到Class对象所表征的类的所有属性(包括私有属性)
  500. Field[] fields = sourceClz.getDeclaredFields();
  501. for (int i = 0; i < fields.length; i++) {
  502. String fieldName = fields[i].getName();
  503. String targetFieldName = fieldName.toLowerCase();
  504. Field targetField = null;
  505. try {
  506. // 得到targetClz对象所表征的类的名为fieldName的属性,不存在就进入下次循环
  507. targetField = targetClz.getDeclaredField(targetFieldName);
  508. } catch (SecurityException e) {
  509. e.printStackTrace();
  510. break;
  511. } catch (NoSuchFieldException e) {
  512. continue;
  513. }
  514. // 判断sourceClz字段类型和targetClz同名字段类型是否相同
  515. if (fields[i].getType() == targetField.getType()
  516. || (fields[i].getType() == Long.class && targetField.getType() == String.class)
  517. || (fields[i].getType() == Integer.class && targetField.getType() == String.class)
  518. || (fields[i].getType() == Double.class && targetField.getType() == String.class)
  519. || (fields[i].getType() == Float.class && targetField.getType() == String.class)
  520. || (fields[i].getType() == Date.class && targetField.getType() == String.class)){
  521. // 由属性名字得到对应get和set方法的名字
  522. String getMethodName = "get"
  523. + fieldName.substring(0, 1).toUpperCase()
  524. + fieldName.substring(1);
  525. String setMethodName = "set"
  526. + targetFieldName.substring(0, 1).toUpperCase()
  527. + targetFieldName.substring(1);
  528. // 由方法的名字得到get和set方法的Method对象
  529. Method getMethod;
  530. try {
  531. getMethod = sourceClz.getDeclaredMethod(getMethodName,
  532. new Class[] {});
  533. Method setMethod = targetClz.getDeclaredMethod(
  534. setMethodName, String.class);
  535. // 调用source对象的getMethod方法
  536. Object result = getMethod.invoke(source, new Object[] {});
  537. if(fields[i].getType() == Date.class){
  538. if(result != null){
  539. Date date = (Date) result;
  540. SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  541. result = dateFormat.format(date);
  542. }
  543. }
  544. if(result == null){
  545. result = "";
  546. }
  547. // 调用target对象的setMethod方法
  548. setMethod.invoke(target, result==null?null:new String(result.toString()));
  549. } catch (SecurityException e) {
  550. // TODO Auto-generated catch block
  551. e.printStackTrace();
  552. } catch (NoSuchMethodException e) {
  553. // TODO Auto-generated catch block
  554. e.printStackTrace();
  555. } catch (IllegalArgumentException e) {
  556. // TODO Auto-generated catch block
  557. e.printStackTrace();
  558. } catch (IllegalAccessException e) {
  559. // TODO Auto-generated catch block
  560. e.printStackTrace();
  561. } catch (InvocationTargetException e) {
  562. // TODO Auto-generated catch block
  563. e.printStackTrace();
  564. }
  565. } else {
  566. new Exception("同名属性类型不匹配!").printStackTrace();
  567. }
  568. }
  569. }
  570. /**
  571. * <p>
  572. * Description:[删除对象中的基类属性的值]
  573. * </p>
  574. * @param recordBO
  575. *
  576. * @author wangjinping
  577. */
  578. public static void removeBaseAttributeValue(RecordBO recordBO){
  579. recordBO.setCreatedBy(null);
  580. recordBO.setCreationMethod(null);
  581. recordBO.setCreationTime(null);
  582. recordBO.setUpdatedBy(null);
  583. recordBO.setUpdateMethod(null);
  584. recordBO.setUpdateTime(null);
  585. recordBO.setDeleteFlag(0);
  586. }
  587. }