反射模拟DbUtils实现ResultSet转成Bean实例
2016-07-18 16:07
274 查看
前几天接触到了
当时真的是感觉到很是神奇,仅仅是指定了一下那个Bean类的全名,就能从数据库结果集中自动的生成我们需要的Bean对象,真的是太优雅了。然后我就翻了翻源码,然后尴尬的发现自己能力有限,并不能真正做出那样强大而且优雅的东西。
下面是一个简单的入门级的小例子
接下来就是重头戏了。
今天代码中的闪光点在于:
好了,今天的分享就先到这里吧。希望这个思路能给看到这篇文章的童鞋一丝启发,开发出专属于自己的一套小工具。
apache的一个小框架
DbUtils,真的被其优雅的设计所震撼到了,尤其是其中的
MyBean mybean = QueryRunner.query(sqlConnection,sqlStatement,new BeanHandler<MyBean.class>(),params);
当时真的是感觉到很是神奇,仅仅是指定了一下那个Bean类的全名,就能从数据库结果集中自动的生成我们需要的Bean对象,真的是太优雅了。然后我就翻了翻源码,然后尴尬的发现自己能力有限,并不能真正做出那样强大而且优雅的东西。
反射技术
虽然写不了那样强大的框架,但是模拟一下还是可行的嘛,我在源码中看到了反射技术的影子,然后就恶补了一下相关的知识点。细节方面主要是使用到了PropertyDescriptor这个类,以及相关的
getReadMethod和
getWriteMethod。说白了就是实现setter和getter方法。
下面是一个简单的入门级的小例子
// 这个小例子就包含了getter方法和setter的使用了 public static <T> void test1(String proName, Class<T> beanCLass) throws Exception { PropertyDescriptor pd = new PropertyDescriptor(proName, beanCLass); String type = pd.getPropertyType().toString(); Method setMethod = pd.getWriteMethod(); // Person p = new Person(); T p = (T) beanCLass.newInstance(); // 这里也仅仅是做个示例,只允许String类型的Property来赋值,否则会报错的 setMethod.invoke(p, "郭璞"); System.out.println(pd.getReadMethod().invoke(p, null)); }
获取所有的Properties
经过了上面的小例子,那我们就具备了给单个的Property赋值的实现了,至于怎么给一个Bean的所有的
Property赋值,请接着往下看。
beanClass.getDeclaredFields().有了这行代码,我们就可以接着下一步了。
// 使用下面的这个方法,我们就可以轻松的获取一个Bean的所有的 Properties了 public static <T> Field[] getFields(Class<T> clazz) throws Exception { String qualifyName = new String(clazz.toString().substring(6, clazz.toString().length())); qualifyName.concat(".class"); System.out.println("Qualify Name:" + qualifyName); Class cls = Class.forName(qualifyName); Field[] fields = cls.getDeclaredFields(); return fields; }
我的小框架
为了接下来的测试成功,我们先new出来几个Bean吧。分别如下:/** * @Date 2016年7月18日 * * @author Administrator */ package com.grb.one; /** * @author 郭璞 * */ public class Person { private String name; private int age; public Person() { } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Person(String name) { this.name = name; } @Override public String toString() { return "Person [name=" + name + ", age=" + age + "]"; } } /** * @Date 2016年7月18日 * * @author Administrator */ package com.grb.one; /** * @author 郭璞 * */ public class Dog { public String volun; private String name; public String getVolun() { return volun; } public void setVolun(String volun) { this.volun = volun; } public Dog() { } @Override public String toString() { return "Dog [volun=" + volun + ", name=" + name + "]"; } /** * @param name * the name to set */ public void setName(String name) { this.name = name; } /** * @return the name */ public String getName() { return name; } public void run(Integer mails) { System.out.println("This dog runned:" + mails + " mails.!"); } }
接下来就是重头戏了。
/** * @Date 2016年7月18日 * * @author Administrator */ package neixing; import java.beans.PropertyDescriptor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; import com.grb.one.Dog; import com.grb.one.Person; /** * @author 郭璞 * */ public class Demo { public static void main(String[] args) throws Exception { test1("name", com.grb.one.Person.class); System.out.println("----------------------------------------"); test2(); System.out.println("----------------------------------------"); test3(); } public static void test2() throws Exception { Map<String, Object> resultset = new HashMap<String, Object>(); resultset.put("name", "person-name-property"); resultset.put("age", 20); Person p = (Person) createBean(resultset, com.grb.one.Person.class); System.out.println(p.toString()); } public static void test3() throws Exception { Map<String, Object> resultset = new HashMap<String, Object>(); resultset.put("volun", "dog-volun-property"); resultset.put("name", "dog-name-property"); Dog dog = (Dog) createBean(resultset, com.grb.one.Dog.class); System.out.println(dog.toString()); } public static <T> Field[] getFields(Class<T> clazz) throws Exception { String qualifyName = new String(clazz.toString().substring(6, clazz.toString().length())); qualifyName.concat(".class"); System.out.println("Qualify Name:" + qualifyName); Class cls = Class.forName(qualifyName); Field[] fields = cls.getDeclaredFields(); return fields; } public static <T> T createBean(Map<String, Object> resultset, Class<T> bean) throws Exception { T mybean = bean.newInstance(); Field[] fields = getFields(bean); for (Field field : fields) { PropertyDescriptor pd = new PropertyDescriptor(field.getName(), bean); Method setter = pd.getWriteMethod(); setter.invoke(mybean, resultset.get(field.getName())); } return mybean; } }
测试结果
下面就来一起看看振奋人心的结果吧。郭璞 ---------------------------------------- Qualify Name:com.grb.one.Person Person [name=person-name-property, age=20] ---------------------------------------- Qualify Name:com.grb.one.Dog Dog [volun=dog-volun-property, name=dog-name-property]
总结
反射技术对于泛型的使用可谓是登峰造极了。这样做的好处不言而喻。今天代码中的闪光点在于:
String.subString();// 分割字符串,实现bean的全名转化成可反射的字符串类型
Map<String,Object>的使用,好处在于模拟了
ResultSet,提供了素材
Class<T> bean的使用,神奇的一种方式啊。泛型的优点可不仅仅在这里能看到啊。:-)
好了,今天的分享就先到这里吧。希望这个思路能给看到这篇文章的童鞋一丝启发,开发出专属于自己的一套小工具。
相关文章推荐
- spring4 mvc 出错
- 反射模拟DbUtils实现ResultSet转成Bean实例
- Ajax获取显示Json数据的一种方法
- NOIP2012拓展欧几里得
- LUA基础
- 页面显示(pageshow)和页面隐藏(pagehide)事件
- caffe源码阅读3-blob.cpp
- JVM性能调优
- 有名管道总结
- 新浪分享授权登录
- 游戏测试------------第5章
- ACM HDU 1061 Rightmost Digit
- hdu--1879继续畅通工程
- android开发五子棋人人对战
- JSP自定义标签
- cesiumjs开发实践 (四)
- UISearchController的searchBar点击消失的问题解决
- 最频繁访问驻留缓存算法
- Leetcode 58. Length of Last Word (Easy) (cpp)
- 【HDU 4006】The kth great number(优先队列)