欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Eclipse下Javassist正确使用方法代码解析

程序员文章站 2024-02-15 19:56:34
这两天看到hibernate的代理部分,第一反应是底层使用了反射,针对用户实体生成了代理类,后来反应过来了,反射没有任何可以产生新类的能力,也就顺理成章地找到了javass...

这两天看到hibernate的代理部分,第一反应是底层使用了反射,针对用户实体生成了代理类,后来反应过来了,反射没有任何可以产生新类的能力,也就顺理成章地找到了javassist()。

在网上搜索到的大部分教程,都是针对javassist的api进行一番讲解,但是最后,往往没有一个加载过程,而笔者模仿这些教程进行类的加载时,加载到的结果都是原来的类,并没有产生字节码被修改的内容。

在经过一番探索后,笔者发现,网上的大部分教程中的最后一步,保存字节码,使用的均是writefile的无参数重载,在查看其函数结构后发现,它还有一个string类型的重载,由于在eclipse下,字节码储存的根位置并不是”.\\”而是”.\\bin”,而writefile的另一个重载很可能是指定字节码根位置的参数,笔者进行一番更改后发现,果不其然。

下面将演示代码分享出来:

这是笔者项目的结构:

Eclipse下Javassist正确使用方法代码解析

editable.java: 
package com.thrblock.javassist; 
  
public class editable { 
   public void showinfo(){ 
       system.out.println("infodefault!"); 
   } 
} 
main.java: 
package com.thrblock.javassist;
import java.io.ioexception;
import javassist.cannotcompileexception;
import javassist.classpool;
import javassist.ctclass;
import javassist.ctmethod;
import javassist.ctnewmethod;
import javassist.notfoundexception;
public class main {
	public static void main(string[] args) {
		classpool pool = classpool.getdefault();
		try{
			pool.insertclasspath(".\\bin");
			//设置根路径。(这里设置的根路径显然没被writefile使用) 
			ctclass cc = pool.makeclass("com.thrblock.javassist.editablechanged");
			//模拟hibernate代理模式,我们创建一个新类 
			cc.setsuperclass(pool.get("com.thrblock.javassist.editable"));
			//设置其父类 
			ctmethodcm = ctnewmethod.make("public void showinfo(){super.showinfo();system.out.println(\"custominserthaha!\");}",cc);
			//追加一个方法,注意它覆盖了父类中的方法。 
			cc.addmethod(cm);
			cc.writefile(".\\bin");
			//这里比较重要,空参的结果就是没有保存到eclipse字节码根路径里。
		}
		catch (notfoundexception | cannotcompileexception | ioexception e) {
			e.printstacktrace();
		}
		try{
			class<?> cl = class.forname("com.thrblock.javassist.editablechanged");
			//加载我们的新类 
			editableed = (editable) cl.newinstance();
			//由于其继承与editable类,这里和hibernate里的load道理一样。 
			ed.showinfo();
			//调用方法。
		}
		catch (classnotfoundexception | instantiationexception |illegalaccessexception e) {
			e.printstacktrace();
		}
	}
}

打印结果:

infodefault!

custominserthaha!

其他注意事项:

由于我们是生成了一个类,如果这个类名和原类名一样,则会覆盖class文件,但是如果修改之前该class已经被jvm装入,则修改的部分不会生效,必须重启jvm。

总结

以上就是本文关于eclipse下javassist正确使用方法代码解析的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!