如果大家看过我之前的那一篇关于 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"));
}
}
这两段代码中比较关键的部分我都做了注释,大家可以自行阅览,其中被注释掉的代码,是用来展示创建类过程中的其他功能的,有兴趣钻研的朋友也可以试着运行一下,有什么看不懂的地方,欢迎留言: