借助Java动态反射机制 创建类

来源:互联网 发布:程序员对笔记本尺寸 编辑:程序博客网 时间:2024/06/08 09:36

         如果大家看过我之前的那一篇关于 Java Class类与反射机制 的文章,大家应该对java的动态反射机制有一个初步的了解,这里我们在更进一步,看看java程序能不能自己创建一个java类。

         我们在搭建jsp后台的网站时,通常 mysql数据库中的一个表,就对应这我们java后台的一个类,数据库的表中的一行数据,就对应这我们的一个java后台的一个对象。当我们的数据很大的时候,我们可能需要个数据表,这时候如果我们手动在java后台建立相应的类和对象,就会显得非常的繁琐,有没有什么办法,能帮我们把java的类创建出来呢?

        答案是有的,

       这里我们就来说一下,怎样用java代码创建类:

       先来看两段代码:(这两段代码需要一个外部类,cglib-nodep-2.2.2.jar,不同的cglib库可能会有不兼容的情况,导致错误,这里我提供了我正在使用的cglib-nodep-2.2.2.jar,大家可以在这篇博客页面连接中下载。)

      CglibBean类:

package Dynamic_class3;import java.util.Iterator;public class CglibBean {// 实体Objectpublic Object object = null;// 属性mappublic BeanMap beanMap = null;public CglibBean() {super();}@SuppressWarnings("unchecked")public CglibBean(Map propertyMap) {this.object = generateBean(propertyMap);this.beanMap = BeanMap.create(this.object);}/** * 给bean属性赋值 * @param property *            属性名 * @param value *            值 */public void setValue(String property, Object value) {beanMap.put(property, value);}/** * 通过属性名得到属性值 * @param property *            属性名 * @return 值 */public Object getValue(String property) {return beanMap.get(property);}/** * 得到该实体bean对象 * @return */public Object getObject() {return this.object;}@SuppressWarnings("unchecked")private Object generateBean(Map propertyMap) {BeanGenerator generator = new BeanGenerator();Set keySet = propertyMap.keySet();for (Iterator i = keySet.iterator(); i.hasNext();) {String key = (String) i.next();generator.addProperty(key, (Class) propertyMap.get(key));}return generator.create();}}
      CglibTest测试类:
package Dynamic_class3;import java.lang.reflect.Field;import java.lang.reflect.Method;import java.lang.reflect.Modifier;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;//这个类存在的问题就是它生成的类中的参数的顺序是随机的,不能借助传入时的顺序来找到(必须借助参数的名字),(而动态编译的时候,参数的名字又不可能事先得知)//这里生成的类的属性都是私有的,get和set方法都是公有的。注意使用/** * Cglib测试类 *  * @author cuiran * @version 1.0 */public class CglibTest {// 这里编译类是没有类名的,你需要自己给它取一个名字(比如叫 clazz 啊什么的·····),// 这个函数用来动态的创建类,其中param_type是一个多行,两列的二维数组,第一列是属性名,第二列是属性的类型(Integer,String····),Value是参数的初始值。public static Class create_class(String[][] param_type)throws ClassNotFoundException {// 设置类成员属性HashMap propertyMap = new HashMap();for (int i = 0; i < param_type.length; i++) {propertyMap.put(param_type[i][0],Class.forName("java.lang." + param_type[i][1]));}// 生成动态 BeanCglibBean bean = new CglibBean(propertyMap);// 给 Bean 设置值for (int i = 0; i < param_type.length; i++) {switch (param_type[i][1]) {case "Integer":bean.setValue(param_type[i][0], new Integer(0));break;case "String":bean.setValue(param_type[i][0], new String("xx"));break;case "Float":bean.setValue(param_type[i][0], new Float(0));break;case "Double":bean.setValue(param_type[i][0], new Double(0));break;default:break;}}// 从 Bean 中获取值,当然了获得值的类型是 Objectfor (int i = 0; i < param_type.length; i++) {System.out.println("  >> " + param_type[i][0] + "      = "+ bean.getValue(param_type[i][0]));}// 获得bean的实体Object object = bean.getObject();// 通过反射查看所有方法名Class clazz = object.getClass();// Method[] methods = clazz.getDeclaredMethods();// for (int i = 0; i < methods.length; i++) {// System.out.println(methods[i].getName());// }return clazz;}// 这个函数用来动态的创建类并且获取对象,其中param_type是一个多行,两列的二维数组,第一列是属性名,第二列是属性的类型(Integer,String····),Value是参数的初始值。public static Object create_class_and_object(String[][] param_type,String[] Value) throws ClassNotFoundException {// 设置类成员属性HashMap propertyMap = new HashMap();for (int i = 0; i < param_type.length; i++) {propertyMap.put(param_type[i][0],Class.forName("java.lang." + param_type[i][1]));}// 生成动态 BeanCglibBean bean = new CglibBean(propertyMap);// 给 Bean 设置值for (int i = 0; i < param_type.length; i++) {switch (param_type[i][1]) {case "Integer":bean.setValue(param_type[i][0],new Integer(Integer.parseInt(Value[i])));break;case "String":bean.setValue(param_type[i][0], new String(Value[i]));break;case "Float":bean.setValue(param_type[i][0], new Float(Value[i]));break;case "Double":bean.setValue(param_type[i][0], new Double(Value[i]));break;default:break;}}// 获得bean的实体Object object = bean.getObject();// 通过反射查看所有方法名// Class clazz = object.getClass();// Method[] methods = clazz.getDeclaredMethods();// for (int i = 0; i < methods.length; i++) {// System.out.println(methods[i].getName());// }return object;}// 其中这个参数用来返回一个对象,对象的属性形式是“类型为:class// java.lang.Integer,参数名为:$cglib_prop_id,参数值为:1”,参数顺序仍然是乱的。public Object create_object(class_info clin, String[] str)throws InstantiationException, IllegalAccessException {// 创建相应的对象Object obj = clin.clazz.newInstance();// 通过反射API操作属性Field[] f = clin.clazz.getDeclaredFields();for (int j = 0; j < f.length; j++) {f[j].setAccessible(true);// 这个属性不需要安全检查了,可以直接访问// System.out.println(f[i].getType().toString());String param_name = f[j].getName();// 在类的属性表中查找这个属性,找到相应的类型for (int k = 0; k < f.length; k++) {if (("$cglib_prop_" + clin.param_type[k][0]).equals(param_name)) {// 说明参数名匹配成功// 从参数表中取出参数类型switch (clin.param_type[k][1]) {// 这里数据库中的数据的顺序和class_info中的属性表的顺序是相同的,所以可以直接用参数表的下标号来作为str的下标号case "String":f[j].set(obj, str[k]);// 通过反射直接写属性break;case "Integer":f[j].set(obj, Integer.parseInt(str[k]));// 通过反射直接写属性break;default:System.err.println("这个类中含有暂时没有考虑到的参数-----");break;}break;} else if (k == f.length - 1) {System.out.println("参数表名为:$cglib_prop_"+ clin.param_type[k][0] + ",而类中的属性名为:"+ param_name);System.err.println("发生错误,找不到参数名。");}}// System.out.println(obj.getUname());//通过反射直接读属性的值// System.out.println("新加入的参数类型为:" + f[j].getType().toString()// + ",参数名为:" + f[j].getName() + ",值为:" + f[j].get(obj));}return obj;}static public int find_field(Class clazz, String para_name) {Field[] f = clazz.getDeclaredFields();for (int i = 0; i < f.length; i++) {f[i].setAccessible(true);// 这个属性不需要安全检查了,可以直接访问if (("$cglib_prop_" + para_name).equals(f[i].getName())) {return i;}}return -1;}/** * 获取属性类型(type),属性名(name),属性值(value)的map组成的list 这个函数暂时没办法用,(因为存在问题,无法改正) * */// 这个函数没有问题了static public List getFiledsInfo(Object o) {Field[] fields = o.getClass().getDeclaredFields();String[] fieldNames = new String[fields.length];List list = new ArrayList();Map infoMap = null;for (int i = 0; i < fields.length; i++) {infoMap = new HashMap();infoMap.put("type", fields[i].getType().toString());infoMap.put("name", fields[i].getName());infoMap.put("value", getFieldValueByName(fields[i].getName(), o));list.add(infoMap);}return list;}/** * 根据属性名获取属性值 * */static public Object getFieldValueByName(String fieldName, Object o) {try {// 对属性名做预处理,截去类名的前十二个 无用的字符// fieldName = fieldName.substring(12);// 借助类中的get方法来获取对象的属性的值。String firstLetter = fieldName.substring(0, 1).toUpperCase();String getter = "get" + firstLetter + fieldName.substring(1);//System.out.println("show method name" + getter);Method method = o.getClass().getMethod(getter, new Class[] {});// System.out.println(Modifier.toString(method.getModifiers()));Object value = method.invoke(o, new Object[] {});return value;} catch (Exception e) {e.printStackTrace();}return o;}static public Object getFieldValueByName2(String fieldName, Object o,class_info clin) {Class clazz = o.getClass();Field[] f = clazz.getDeclaredFields();for (int i = 0; i < f.length; i++) {String param_name = f[i].getName();String pa_name = param_name.substring(12);if (fieldName.equals(pa_name)) {try {return f[i].get(o);} catch (IllegalArgumentException e) {// TODO 自动生成的 catch 块e.printStackTrace();} catch (IllegalAccessException e) {// TODO 自动生成的 catch 块e.printStackTrace();}}}return null;}@SuppressWarnings("unchecked")public static void main(String[] args) throws ClassNotFoundException,InstantiationException, IllegalAccessException {//这里定义类中的属性名,和属性的类型,String[][] param = { { "param1", "String" }, { "param2", "Integer" } };//这里定义创建对象时属性的值,String[] v = { "1111", "2222" };//创建一个类Class c = create_class(param);Object ob = create_class_and_object(param, v);System.out.println(getFieldValueByName("param1", ob));// List t = getFiledsInfo((Object) ob);// System.out.println(((HashMap) t.get(0)).get("name"));// test te = new test();// List t = getFiledsInfo((Object)te);// System.out.println(((HashMap)// t.get(0)).get("value"));}}
    这两段代码中比较关键的部分我都做了注释,大家可以自行阅览,其中被注释掉的代码,是用来展示创建类过程中的其他功能的,有兴趣钻研的朋友也可以试着运行一下,有什么看不懂的地方,欢迎留言: