通俗易懂解释java反射机制(二) (模拟 ibatis 的 selectBySql 查询)
JAVA有着一个非常突出的动态相关机制:Reflection,
用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。
换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),
并生成其对象实体、或对其fields设值、或唤起其methods。
JAVA反射机制是在运行状态中,对于任意一个类,
都能够知道这个类的所有属性和方法;
对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
我自己的理解反射其中一个应用:提供这样一个方法: 把类名 当作形参 传入 经过一系列处理后(获得属性 获取方法 等等) 可以返回给你这个类的对象。
关键在与这个类 是你随便写的 是在运行时候动态new出来的
而不是在编译前 程序员自己写的。
作用是 更加灵活 可以复用。
一下是jdbc 的查询方法:(虽然是jdbc 但是也是可以多次复用的公共查询方法)
/** * query data * * @param sql * query data's sql * @return return a list */ @SuppressWarnings("unchecked") public List<Map> selectQuery(String sql) { openConnection(); List<Map> result = new ArrayList<Map>(); try { stmt = conn.prepareStatement(sql,ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); //System.out.println(sql); rs = stmt.executeQuery(); ResultSetMetaData rsm = rs.getMetaData(); int cols = rsm.getColumnCount(); while (rs.next()) { Map<String, String> map = new HashMap<String, String>(); for (int i = 1; i <= cols; i++) { String colName = rsm.getColumnLabel(i); String colValue = rs.getString(i); //System.out.println("colName:\t"+colName+";colValue:\t"+colValue); map.put(colName, colValue); } result.add(map); } } catch (SQLException e) { System.out.println(e.toString()); }finally{ closeConnection(); } return result; }
返回查询到对象的集合 map 的key是字段名 ,value 是字段的值。
接下来用beanFactory 生产出来你想要的任何 bean 的list集合
package com.woyi.util.factory;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.Method;import java.util.ArrayList;import java.util.Iterator;import java.util.List;import java.util.Map;import java.util.Set;public class BeanFactory { /** * @param beanName 对应javaBean包加类名 * @param map * @return */ @SuppressWarnings("unchecked")//beanName是所要封装的目的对象的名字,maplist是从数据库查出来的list public static List ListToBean(String beanName,List<Map> mapList){ List list = new ArrayList(); for (Map<String, String> map : mapList) {//对maplist进行遍历,map里面的key 是数据库表的字段或者其别名, //value就是其对应的值了 try{ Class c = Class.forName(beanName); //加载获得bean的Class对象 Constructor con = c.getConstructor(new Class[]{}); //获得bean的构造器 Object myclass = con.newInstance(new Object[]{}); //用构造器new一个bean的对象 Field[] fields = myclass.getClass().getDeclaredFields();//bean的属性数组 Set set = map.keySet();//获取map里面所有的key值 放到set里面 Iterator<String> iter = set.iterator();//获取set的迭代器 while (iter.hasNext()) {//遍历 String key = iter.next(); for (Field field : fields) { String fieldName = field.getName(); if(key.toLowerCase().equals(field.getName().toLowerCase())){//比较数据库字段名和bean的属性名是否一致// 不区分大小写 若一致 则调用bean的set方法 将字段值set进bean的属性值 String methodName = "set"+fieldName.substring(0,1).toUpperCase()+fieldName.substring(1); //判断bean 属性的类型 if (field.getType().getSimpleName().equals("Integer")) { Method method = c.getDeclaredMethod(methodName,Integer.class);//获取set方法 int value = 0; try { value = Integer.parseInt(map.get(key)); } catch (Exception e) { value = 0; } method.invoke(myclass,value);//调用set方法 }else if(field.getType().getSimpleName().equals("int") ){ Method method = c.getDeclaredMethod(methodName,int.class); int value = 0; try { value = Integer.parseInt(map.get(key)); } catch (Exception e) { value = 0; } method.invoke(myclass,value); }else if(field.getType().getSimpleName().equals("String")){ Method method = c.getDeclaredMethod(methodName,String.class); method.invoke(myclass, map.get(key)); }else if(field.getType().getSimpleName().equals("double")){ Method method = c.getDeclaredMethod(methodName,double.class); double value = 0.0; try { value = Double.parseDouble(map.get(key)); } catch (Exception e) { value = 0.0; } method.invoke(myclass, value); }else if(field.getType().getSimpleName().equals("Double")){ Method method = c.getDeclaredMethod(methodName,Double.class); double value = 0.0; try { value = Double.parseDouble(map.get(key)); } catch (Exception e) { value = 0.0; } method.invoke(myclass, value); }else{ System.out.println("目前只支持int ,double与 String 类型数据属性"); continue; } //以后扩展其他属性类型的解析 } } } list.add(myclass); }catch(Exception e){ e.printStackTrace(); } } return list; }}
最后 强转成 你想要的List<beanName> 接收 就可以了
for example:
public List<HelpInfoConfig> queryHelp1(){ String sql = "select * from help order by id "; DBBase dBBase = new DBBase();//DBBase 是操作数据库的工具类 里面有获取connection select等等方法 List<Map> list= dBBase.selectQuery(sql); List<HelpInfoConfig> help = BeanFactory.ListToBean("com.woyi.bean.HelpInfoConfig", list); return help; }