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

         如果大家看过我之前的那一篇关于 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 {

	// 实体Object
	public Object object = null;

	// 属性map
	public 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]));
		}
		// 生成动态 Bean
		CglibBean 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 中获取值,当然了获得值的类型是 Object
		for (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]));
		}
		// 生成动态 Bean
		CglibBean 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"));
	}
}
     
     
    
    
    这两段代码中比较关键的部分我都做了注释,大家可以自行阅览,其中被注释掉的代码,是用来展示创建类过程中的其他功能的,有兴趣钻研的朋友也可以试着运行一下,有什么看不懂的地方,欢迎留言:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值