您的位置:首页 > 其它

反射模拟DbUtils实现ResultSet转成Bean实例

2016-07-18 16:07 274 查看
前几天接触到了
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
的使用,神奇的一种方式啊。泛型的优点可不仅仅在这里能看到啊。:-)

好了,今天的分享就先到这里吧。希望这个思路能给看到这篇文章的童鞋一丝启发,开发出专属于自己的一套小工具。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: