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

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

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


反射技术

虽然写不了那样强大的框架,但是模拟一下还是可行的嘛,我在源码中看到了反射技术的影子,然后就恶补了一下相关的知识点。细节方面主要是使用到了PropertyDescriptor这个类,以及相关的getReadMethodgetWriteMethod。说白了就是实现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的使用,神奇的一种方式啊。泛型的优点可不仅仅在这里能看到啊。:-)

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

反射模拟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. [JS]手动实现一个横屏滚动公告js插件

    前言 工作中要用到.在github上找的大部分都是竖屏滚动没办法只能自己手动写. 本来只是想随便实现一下的,结果一时兴起把它弄成了一个简单的小插件,开了个github仓库(希望路过点个星) JS横屏滚 ...

  2. mysql-5.7.18-winx64 免安装版配置

    如题,最新的都是只有免安装版的,可以官网下载zip的压缩包. 下载后解压,如下 下面就开始配置 1.在path中添加环境变量 ;D:\coding\mysql-5.7.18-winx64\bin; ← ...

  3. Python3玩转儿 机器学习(2)

    机器学习的基本任务 分类任务 回归任务 分类任务 手写输入数字识别 分类任务: 二分类任务 判断邮件是垃圾邮件或者不是垃圾邮件 判断发放给客户信用卡有风险或者没有风险 判断病患良性肿瘤还是恶性肿瘤 判 ...

  4. [LSGDOJ 1505]售货员的难题 状压DP

    题目描述 某 乡有n个村庄(1<n<15),有一个售货员,他要到各个村庄去售货,各村庄之间的路程s(0<s<1000)是已知的,且A村 到B村与B村到A村的路大多不同.为了提高 ...

  5. 华科机考:a+b

    时间限制:1秒     空间限制:32768K 题目描述 实现一个加法器,使其能够输出a+b的值. 输入描述: 输入包括两个数a和b,其中a和b的位数不超过1000位. 输出描述: 可能有多组测试数据 ...

  6. 如何查看cisco 生成树状态

    如何查看cisco 生成树状态  Role(角色): 1.Desg(指定端口)   2.Root(根端口)    3.Altn(替换端口) Sts(状态): 1.FWD(转发)      2.BLK( ...

  7. Linux学习之CentOS(十一)-----Linux 账号管理(转)

    Linux 账号管理(转) useraddpasswdchageusermoduserdelfingerchfnchshidgroupaddgroupmodgroupdelgpasswd su(帐号切 ...

  8. 基于PHP的快递查询免费开放平台案例-快宝开放平台

    快递查询是快递业务中极其重要的业务,免费的快递查询开放平台:快宝开放平台. 快宝开放平台:http://open.kuaidihelp.com/home,已经对接100多家快递公司,实现快递物流信息实 ...

  9. 装 ubuntu + win10 出现 grub rescue 并处理之

    开机出现 grub rescue 原因:装 ubuntu + win10 双系统时有可能搞坏启动文件. grub rescue 隶属于 ubuntu管理. grub rescue 里可用命令很少,主要 ...

  10. 63. Unique Paths II(中等, 能独立做出来的DP类第二个题^^)

    Follow up for "Unique Paths": Now consider if some obstacles are added to the grids. How m ...