起初采用Commons beanutils的分析对象的方法,获取所有属性的值,构建格式输出;
如有以下的Class
class LabelView implements View { private String id; private String value; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } }
有对应的类
LabelView label = new LabelView(); label.setId("label1"); label.setValue("Hello, world.");
前端需要的输出格式内容为
另有以下的Class
class TextfieldView implements View { private String id; private String name; private String value; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } }
有对应的类
TextfieldView textfield = new TextfieldView(); textfield.setId("field1"); textfield.setName("field1"); textfield.setValue("张三");
前端需要的输出格式内容为
实际使用的时候,由于存在众多的界面对象描述类需要解析,发现beanutils的时间效率比较低下;
后来考虑采用字节码操作工具对类进行改写,达到自动生成toString()方法的目的;比较了asm和javassist,发现asm的代码太复杂了,所以决定采用javassist;
对class的属性分析代码与beanutils的方式类似,只是需要新生成一个class而已;
过程是这样的:
[list]
ClassPool pool = ClassPool.getDefault(); pool.insertClassPath(new ClassClassPath(View.class)); CtClass ccOld = pool.get(className); CtClass ccNew = pool.makeClass(className + "Access"); ccNew.setSuperclass(ccOld);
CtMethod[] methods = ccOld.getMethods(); for (CtMethod method : methods) { if (method.getName().startsWith("set")) { String shortName = method.getName().substring(3); String fieldName = shortName.toLowerCase(); if (method.getParameterTypes()[0].getName().equals(boolean.class.getName())) { // is } else { // get } } }
String n = ..; // TODO 取得className LabelView对应的输出名称label StringBuffer strbuff = new StringBuffer(); strbuff.append("java.lang.StringBuffer sb = new java.lang.StringBuffer();"); strbuff.append("sb.append(\"<" + n + "\");"); // TODO 以下代码嵌入上面的循环内部 if (method.getParameterTypes()[0].getName().equals(boolean.class.getName())) { strbuff.append("sb.append(\" " + fieldName + "=\\\"\"+is" + shortName + "()+\"\\\"\");"); } else { strbuff.append("sb.append(\" " + fieldName + "=\\\"\"+get" + shortName + "()+\"\\\"\");"); } strbuff.append("sb.append(\">\");"); strbuff.append("sb.append(\"" + n + ">\");"); strbuff.append("return sb.toString();"); CtMethod sm = new CtMethod(pool.get("java.lang.String"), "toString", null, ccNew); sm.setBody("{" + strbuff.toString() + "}"); ccNew.addMethod(sm);
MapclassMap = new HashMap (); classMap.put(className, ccNew.toClass());
classMap.get(className).newInstance().toString();
[/list]
采用javassist之后,时间效率明显提高,基本上就等于手写的toString方法