`
xsmart
  • 浏览: 11027 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

使用Javassist重写Java Bean的toString方法

阅读更多
项目中有很多的界面对象描述类,他们都是接口View的实现,在输出的时候,需要按照特定格式输出成xml表现;

起初采用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.");

前端需要的输出格式内容为
<label id="label1" value="Hello, world."></label>


另有以下的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("张三");

前端需要的输出格式内容为
<textfield id="field1" name="field1" value="张三"></textfield>



实际使用的时候,由于存在众多的界面对象描述类需要解析,发现beanutils的时间效率比较低下;

后来考虑采用字节码操作工具对类进行改写,达到自动生成toString()方法的目的;比较了asm和javassist,发现asm的代码太复杂了,所以决定采用javassist;

对class的属性分析代码与beanutils的方式类似,只是需要新生成一个class而已;

过程是这样的:
[list]
  • 通过javassist生成一个新的class,如LabelView,则生成LabelViewAccess extends LabelView
  • ClassPool pool = ClassPool.getDefault();
    pool.insertClassPath(new ClassClassPath(View.class));
    
    CtClass ccOld = pool.get(className);
    CtClass ccNew = pool.makeClass(className + "Access");
    ccNew.setSuperclass(ccOld);
    
  • 读取LabelView的结构,取得所有的get和is方法
  • 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
    		}
    	}
    }
    
    
  • 利用javassist构建toString()方法,将上面取得的方法进行字符串拼接
  • 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);
    
    
  • 调用javassist的CtClass.toClass()方法返回LabelView的真实class LabelViewAccess,并存储起来备用
  • Map<String, Class> classMap = new HashMap<String, Class>();
    classMap.put(className, ccNew.toClass());
    
    
  • 使用的时候,获得上面的LabelViewAccess,然后class.getConstructor().newInstance()获取带有格式化输出toString方法的LabelView对象
  • classMap.get(className).newInstance().toString();
    

    [/list]

    采用javassist之后,时间效率明显提高,基本上就等于手写的toString方法
    分享到:
    评论

    相关推荐

      借助jclasslib与javassist修改java class字节码

      ### 借助jclasslib与javassist修改Java class字节码 #### 一、引言 在软件开发过程中,有时我们可能面临一种情况:即需要对已经编译好的`.class`文件进行修改,但手中并没有对应的源代码。这种情况下,我们可以...

      javaagent+javassist

      总的来说,javaagent和javassist的结合使用为Java开发者提供了强大的代码操作能力,允许我们在运行时对应用程序进行灵活的扩展和修改,极大地提升了开发的灵活性和效率。在实际项目中,如Spring AOP、AspectJ等框架...

      javassist,Java字节码工程工具包.zip

      6. **兼容性**:Javassist与Java标准库的`java.lang.ClassLoader`和`java.lang.reflect`紧密集成,因此可以无缝地与其他Java应用和库配合使用。同时,它支持从Java 1.4到最新的Java版本,确保了广泛的兼容性。 7. *...

      javassist, Java字节码工程工具包.zip

      javassist, Java字节码工程工具包 Java字节码工程工具包 版本 3版权所有( C ) 1999 -2017按 Shigeru Chiba,保留所有权利。Javassist ( Java编程助手) 使Java字节码操作简单。 它是一个类库,用于在Java中编辑字节码

      JavaAgent:Javassist 与 Asm JavaAgent 字节码动态编程项目

      通过这个“JavaAgent: Javassist与Asm JavaAgent字节码动态编程项目”,你将有机会亲自动手实践,理解如何使用这两个库来创建JavaAgent,以及如何在运行时动态修改字节码。项目中可能包含示例代码、教程文档,以及一...

      javassist+javaAgent探针, 实现jvm退出时打印线程栈日志

      javassist+javaAgent探针, 实现jvm退出时打印线程栈日志,方便排查是哪个线程调用了退出,以及退出码

      java 反编译工具 jboss-javassist

      Java反编译工具JBoss Javassist是一款强大的Java字节码操作库,它允许程序员在运行时修改类或者创建新的类。Javassist是Java字节码操纵和分析框架,常用于动态代理、AOP(面向切面编程)以及逆向工程等场景。通过这...

      javassist-3.21.0-GA-API文档-中文版.zip

      赠送jar包:javassist-3.21.0-GA.jar;...使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和结构保持不变,注释和说明精准翻译,请放心使用。

      Javassistjar包

      它已加入了开放源代码JBoss 应用服务器项目,通过使用Javassist对字节码操作为JBoss实现动态"AOP"框架。 关于java字节码的处理,目前有很多工具,如bcel,asm。不过这些都需要直接跟虚拟机指令打交道。如果你不想了解...

      动态代理-jdk、cglib、javassist.zip

      2. 实现InvocationHandler接口,重写invoke方法,该方法会在代理对象的方法被调用时执行。 3. 使用Proxy.newProxyInstance方法创建代理对象,传入类加载器、接口列表和InvocationHandler实例。 4. 通过代理对象调用...

      Javassist 修改class字节码

      Javassist 提供了java类库,用于方便操控Java字节码。功能包括:运行时创建java class,修改class。与其他同类工具(asm等)不同的是,Javassist提供了两个层面的API: 1.java代码层 2.字节码层 通过java代码层,...

      使用javassist修改class文件.pdf

      使用javassist修改class文件.pdf

      javassist官方手册(中文)

      如果 ClassPool.doPruning() 方法设置为 true,Javassist 可以优化调整一个被冻结的 CtClass 对象的数据结构,减少内存使用。 七、结论 Javassist 是一个功能强大且灵活的字节码操作框架,提供了一种灵活的方式来...

      agent+javassist例子

      在IT行业中,`Java Agent`和`javassist`是两个非常关键的技术,它们在软件开发、测试和性能优化中发挥着重要作用。`Java Agent`允许我们对Java应用程序进行预处理,比如字节码注入,而`javassist`库则提供了一个方便...

      javassist试图简化Java字节码的编辑

      `javassist`库正是这样一个工具,它为Java字节码操作提供了一个简洁的API,试图降低这个过程的复杂性。在Java世界中,字节码编辑通常用于动态代理、AOP(面向切面编程)、性能优化以及调试等场景。 `javassist`库是...

      javassist-3.19.0-GA-API文档-中文版.zip

      赠送jar包:javassist-3.19.0-GA.jar;...使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和结构保持不变,注释和说明精准翻译,请放心使用。

      使用Javassist对.class文件进行修改.doc

      在给定的例子中,展示了如何使用 Javassist 修改已有的 `.class` 文件中的方法。以下是一些关键知识点: 1. **ClassPool**: `ClassPool` 类是 Javassist 的核心组件,它管理着一系列的 `CtClass` 对象,这些对象...

      javassist-3.23.1-GA-API文档-中文版.zip

      赠送jar包:javassist-3.23.1-GA.jar;...使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和结构保持不变,注释和说明精准翻译,请放心使用。

      javassistDemo.zip

      总结来说,"javassistDemo.zip"是一个实践教程,通过实例演示了如何使用Javaassist库来动态修改Java类,包括插入新的方法和改变方法的实现。这对于理解和掌握Java运行时代码修改技术,尤其是对于那些需要在运行时...

    Global site tag (gtag.js) - Google Analytics