前几天接触到了apache的一个小框架DbUtils,真的被其优雅的设计所震撼到了,尤其是其中的

  1. MyBean mybean = QueryRunner.query(sqlConnection,sqlStatement,new BeanHandler<MyBean.class>(),params);

当时真的是感觉到很是神奇,仅仅是指定了一下那个Bean类的全名,就能从数据库结果集中自动的生成我们需要的Bean对象,真的是太优雅了。然后我就翻了翻源码,然后尴尬的发现自己能力有限,并不能真正做出那样强大而且优雅的东西。


反射技术

虽然写不了那样强大的框架,但是模拟一下还是可行的嘛,我在源码中看到了反射技术的影子,然后就恶补了一下相关的知识点。细节方面主要是使用到了PropertyDescriptor这个类,以及相关的getReadMethodgetWriteMethod。说白了就是实现setter和getter方法。

下面是一个简单的入门级的小例子

  1. // 这个小例子就包含了getter方法和setter的使用了
  2. public static <T> void test1(String proName, Class<T> beanCLass) throws Exception {
  3. PropertyDescriptor pd = new PropertyDescriptor(proName, beanCLass);
  4. String type = pd.getPropertyType().toString();
  5. Method setMethod = pd.getWriteMethod();
  6. // Person p = new Person();
  7. T p = (T) beanCLass.newInstance();
  8. // 这里也仅仅是做个示例,只允许String类型的Property来赋值,否则会报错的
  9. setMethod.invoke(p, "郭璞");
  10. System.out.println(pd.getReadMethod().invoke(p, null));
  11. }

获取所有的Properties

经过了上面的小例子,那我们就具备了给单个的Property赋值的实现了,至于怎么给一个Bean的所有的Property赋值,请接着往下看。

beanClass.getDeclaredFields().有了这行代码,我们就可以接着下一步了。

  1. // 使用下面的这个方法,我们就可以轻松的获取一个Bean的所有的
  2. Properties
  3. public static <T> Field[] getFields(Class<T> clazz) throws Exception {
  4. String qualifyName = new String(clazz.toString().substring(6, clazz.toString().length()));
  5. qualifyName.concat(".class");
  6. System.out.println("Qualify Name:" + qualifyName);
  7. Class cls = Class.forName(qualifyName);
  8. Field[] fields = cls.getDeclaredFields();
  9. return fields;
  10. }

我的小框架

为了接下来的测试成功,我们先new出来几个Bean吧。分别如下:

  1. /**
  2. * @Date 2016年7月18日
  3. *
  4. * @author Administrator
  5. */
  6. package com.grb.one;
  7. /**
  8. * @author 郭璞
  9. *
  10. */
  11. public class Person {
  12. private String name;
  13. private int age;
  14. public Person() {
  15. }
  16. public String getName() {
  17. return name;
  18. }
  19. public void setName(String name) {
  20. this.name = name;
  21. }
  22. public int getAge() {
  23. return age;
  24. }
  25. public void setAge(int age) {
  26. this.age = age;
  27. }
  28. public Person(String name) {
  29. this.name = name;
  30. }
  31. @Override
  32. public String toString() {
  33. return "Person [name=" + name + ", age=" + age + "]";
  34. }
  35. }
  36. /**
  37. * @Date 2016年7月18日
  38. *
  39. * @author Administrator
  40. */
  41. package com.grb.one;
  42. /**
  43. * @author 郭璞
  44. *
  45. */
  46. public class Dog {
  47. public String volun;
  48. private String name;
  49. public String getVolun() {
  50. return volun;
  51. }
  52. public void setVolun(String volun) {
  53. this.volun = volun;
  54. }
  55. public Dog() {
  56. }
  57. @Override
  58. public String toString() {
  59. return "Dog [volun=" + volun + ", name=" + name + "]";
  60. }
  61. /**
  62. * @param name
  63. * the name to set
  64. */
  65. public void setName(String name) {
  66. this.name = name;
  67. }
  68. /**
  69. * @return the name
  70. */
  71. public String getName() {
  72. return name;
  73. }
  74. public void run(Integer mails) {
  75. System.out.println("This dog runned:" + mails + " mails.!");
  76. }
  77. }

接下来就是重头戏了。

  1. /**
  2. * @Date 2016年7月18日
  3. *
  4. * @author Administrator
  5. */
  6. package neixing;
  7. import java.beans.PropertyDescriptor;
  8. import java.lang.reflect.Field;
  9. import java.lang.reflect.Method;
  10. import java.util.HashMap;
  11. import java.util.Map;
  12. import com.grb.one.Dog;
  13. import com.grb.one.Person;
  14. /**
  15. * @author 郭璞
  16. *
  17. */
  18. public class Demo {
  19. public static void main(String[] args) throws Exception {
  20. test1("name", com.grb.one.Person.class);
  21. System.out.println("----------------------------------------");
  22. test2();
  23. System.out.println("----------------------------------------");
  24. test3();
  25. }
  26. public static void test2() throws Exception {
  27. Map<String, Object> resultset = new HashMap<String, Object>();
  28. resultset.put("name", "person-name-property");
  29. resultset.put("age", 20);
  30. Person p = (Person) createBean(resultset, com.grb.one.Person.class);
  31. System.out.println(p.toString());
  32. }
  33. public static void test3() throws Exception {
  34. Map<String, Object> resultset = new HashMap<String, Object>();
  35. resultset.put("volun", "dog-volun-property");
  36. resultset.put("name", "dog-name-property");
  37. Dog dog = (Dog) createBean(resultset, com.grb.one.Dog.class);
  38. System.out.println(dog.toString());
  39. }
  40. public static <T> Field[] getFields(Class<T> clazz) throws Exception {
  41. String qualifyName = new String(clazz.toString().substring(6, clazz.toString().length()));
  42. qualifyName.concat(".class");
  43. System.out.println("Qualify Name:" + qualifyName);
  44. Class cls = Class.forName(qualifyName);
  45. Field[] fields = cls.getDeclaredFields();
  46. return fields;
  47. }
  48. public static <T> T createBean(Map<String, Object> resultset, Class<T> bean) throws Exception {
  49. T mybean = bean.newInstance();
  50. Field[] fields = getFields(bean);
  51. for (Field field : fields) {
  52. PropertyDescriptor pd = new PropertyDescriptor(field.getName(), bean);
  53. Method setter = pd.getWriteMethod();
  54. setter.invoke(mybean, resultset.get(field.getName()));
  55. }
  56. return mybean;
  57. }
  58. }

测试结果

下面就来一起看看振奋人心的结果吧。

  1. 郭璞
  2. ----------------------------------------
  3. Qualify Name:com.grb.one.Person
  4. Person [name=person-name-property, age=20]
  5. ----------------------------------------
  6. Qualify Name:com.grb.one.Dog
  7. Dog [volun=dog-volun-property, name=dog-name-property]

总结

反射技术对于泛型的使用可谓是登峰造极了。这样做的好处不言而喻。

今天代码中的闪光点在于:

  • String.subString(); // 分割字符串,实现bean的全名转化成可反射的字符串类型

  • Map<String,Object>的使用,好处在于模拟了ResultSet,提供了素材

  • Class<T> bean的使用,神奇的一种方式啊。泛型的优点可不仅仅在这里能看到啊。:-)

好了,今天的分享就先到这里吧。希望这个思路能给看到这篇文章的童鞋一丝启发,开发出专属于自己的一套小工具。

反射模拟DbUtils实现ResultSet转成Bean实例的更多相关文章

  1. 采用dom4j和反射模拟Spring框架的依赖注入功能

    Spring的依赖注入是指将对象的创建权交给Spring框架,将对象所依赖的属性注入进来的行为.在学习了dom4j后,其实也可以利用dom4j和反射做一个小Demo模拟Spring框架的这种功能.下面 ...

  2. 利用反射将Datatable、SqlDataReader转换成List模型

    1. DataTable转IList public class DataTableToList<T>whereT :new() { ///<summary> ///利用反射将D ...

  3. SpringMVC中出现" 400 Bad Request "错误(用@ResponseBody处理ajax传过来的json数据转成bean)的解决方法

    最近angularjs post到后台 400一头雾水 没有任何错误. 最后发现好文,感谢作者 SpringMVC中出现" 400 Bad Request "错误(用@Respon ...

  4. 3.Spring-用反射模拟IoC

    1.BeanFactory.java package com.jike.spring.chapter03.reflect; import java.io.InputStream; import jav ...

  5. 简单的map转换成Bean的工具

    简单的map转换成Bean的工具 package com.sd.microMsg.util; import java.lang.reflect.Field; import java.lang.refl ...

  6. 模拟DbUtils实现接口回调机制

    想必大家都用过apache 的DbUtils吧,这个简单的对JDBC的封装小框架真的是非常非常的适合新手的学习呢.逻辑上也不是很复杂,难度刚刚好. 下面我就模仿它来实现一个字符串的处理小框架. 思路 ...

  7. 利用泛型和反射,管理配置文件,把Model转换成数据行,并把数据行转换成Model

    利用泛型和反射,管理配置文件,把Model转换成数据行,并把数据行转换成Model   使用场景:网站配置项目,为了便于管理,网站有几个Model类来管理配置文件, 比如ConfigWebsiteMo ...

  8. 使用反射创建Bean、Spring中是如何根据类名配置创建Bean实例、Java提供了Class类获取类别的字段和方法,包括构造方法

    Java提供了Class类,可以通过编程方式获取类别的字段和方法,包括构造方法    获取Class类实例的方法:   类名.class   实例名.getClass()   Class.forNam ...

  9. 在Spring Bean实例过程中,如何使用反射和递归处理的Bean属性填充?

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! <Spring 手撸专栏>目录 [x] 第 1 章:开篇介绍,我要带你撸 Spri ...

随机推荐

  1. JavaScript数组操作总结

    以前特别相信自己的大脑,后来,再也不相信了!大脑是虚无的,重要的东西一定要让它有一个物质的具体的副本.事无巨细! 1.创建数组: new Array(); new Array(size); new A ...

  2. Scrapy命令行基本用法

    1.创建一个新项目: scrapy startproject myproject 2.在新项目中创建一个新的spider文件: scrapy genspider mydomain mydomain.c ...

  3. ●BZOJ 2209 [Jsoi2011]括号序列

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=2209 题解: Splay 很好的题,但是把智障的我给恶心到了...   首先不难发现,最后没 ...

  4. HDU5339——Untitled

    Problem Description There is an integer a and n integers b1,…,bn. After selecting some numbers from  ...

  5. hdu5569 BestCoder Round #63 (div.2)

    题意: 给你一个矩阵,要求从左上角走到右下角,走个的费用:a[1]*a[2] + a[3]*a[4] + ......+ a[2n-1]*a[2n] 思路: 果然不机智,自己把自己套路了 对于每个奇数 ...

  6. shell基本命令

    linux基本命令和shell基本命令,好多人傻傻分不清. linux基本命令积累如下: pwd:显示当前工作目录 cd:改变当前目录 ls:显示当前目录中所有目录文件和文本文件 ls -F:显示当前 ...

  7. C语言作业程序设计第一次作业

    1.求圆面积和面积 (1)题目: 输入圆的半径,计算圆的周长和面积 (2)流程图: (3)测试数据及运行结果 测试数据:r=4 运行结果: (4)实验分析 没有遇到问题 2.判断闰年问题 (1)题目: ...

  8. Postgresql合并年月日、月份和日期左侧补零

    在写一个统计查询的 SQL 语句时,需要根据年.月.日分组,但要求返回的字段是日期格式:yyyy年MM月dd日.刚开始我的做法是返回年.月.日,然后再手动拼接年月日,而且还要判断月份和日期是否为个位数 ...

  9. Mybatis自动生成实体类和实体映射工具

    Mybatis Mysql生成实体类 用到的Lib包: mybatis-generator-core-1.3.2.jarmysql-connector-java-5.1.30.jar 1. 创建一个文 ...

  10. 18. 4Sum(中等)

    Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = tar ...