游戏电视苹果数码历史美丽
投稿投诉
美丽时装
彩妆资讯
历史明星
乐活安卓
数码常识
驾车健康
苹果问答
网络发型
电视车载
室内电影
游戏科学
音乐整形

字节码编程丨使用Javassist生成JavaBean

  这种方式几乎不需要修改源程序就能够达到我们想要的效果。今天,我们就一起使用Javassist来动态生成JavaBean对象。
  掌握这个知识点后以便后续我们在手撸DAPM(分布式性能管理系统)时能够动态生成JavaBean对象来反序列化客户端发送的数据,或者从服务端响应回来的数据。开发环境JDK1。8IDEA2018。03Maven3。6。0Maven依赖
  在项目的pom。xml文件中添加如下环境依赖。propertiesjavassist。version3。20。0GAjavassist。versionpropertiesdependenciesdependencygroupIdorg。javassistgroupIdjavassistartifactIdversion{javassist。version}versiondependencydependencies案例效果
  整体案例的效果比较简单,就是通过运行我们写的程序,能够动态生成User类的class字节码。如下所示。packageio。binghe。bytecode。javassist。bean;publicclassUser{privateStringnamebinghe;publicUser(){this。namebinghe;}publicUser(Stringvar1){this。namevar1;}publicvoidsetName(Stringvar1){this。namevar1;}publicStringgetName(){returnthis。name;}publicvoidprintName(){System。out。println(this。name);}}在这个User类中,有一个成员变量name,默认值为binghe。分别有一个无参构造方法和有参构造方法。成员变量name的getset方法。打印成员变量name的方法printName()。
  了解完案例的效果后,我们就开始动手实现如何动态生成这个User类。案例实现
  具体的案例实现,我们可以参考案例的效果一步步完成,这里,我们可以将整个User类的动态生成过程分为6个步骤,分别为:创建User类。添加name字段。添加无参构造方法。添加有参构造方法。添加getset方法。添加printName()方法。
  好了,说干就干,接下来就按照这5个步骤动态生成User类。创建User类使用默认的ClassPoolClassPoolpoolClassPool。getDefault();1。创建一个空类CtClassctClasspool。makeClass(io。binghe。bytecode。javassist。bean。User);
  User类的创建方法和我们之前创建HelloWorld的类是相同的,首先是获取一个ClassPool对象,通过调用ClassPool对象的makeClass方法创建User类。添加name字段2。新增一个字段privateStringname;字段的名称为nameCtFieldparamnewCtField(pool。get(java。lang。String),name,ctClass);设置访问修饰符为privateparam。setModifiers(Modifier。PRIVATE);设置字段的初始值为binghectClass。addField(param,CtField。Initializer。constant(binghe));
  为User类添加成员变量name时,使用了Javassist中的CtField类。这里,我们使用的CtField的构造方法的第一个参数是成员变量的类型,第二个参数是变量的名称,第三个字段表示将这个变量添加到哪个类。
  创建完CtField对象param后,我们调用了param的setModifiers()方法设置访问修饰符,这里将其设置为private。
  接下来,为成员变量name赋默认值binghe。上述代码生成的效果如下所示。privateStringnamebinghe;添加无参构造方法3。添加无参的构造函数CtConstructorconstructornewCtConstructor(newCtClass〔〕{},ctClass);constructor。setBody({0。namebinghe;});ctClass。addConstructor(constructor);
  添加无参构造方法时,使用了Javassist中的CtConstructor类,第一个参数是动态生成的目标类的构造方法的参数类型数组,第二个参数表示将构造方法添加到哪个类中。
  接下来,通过调用CtConstructor的setBody()方法设置无参构造方法的方法体。这里需要注意的是方法体中只有一行代码时,可以省略{},但是为了防止出错,冰河强烈建议无论方法是否只有一行代码,都不要省略{}。
  细心的小伙伴肯定会发现在方法体中通过0引用了成员变量name,估计小伙伴们也猜到了这个0是干啥的。没错,它在生成User类后会被编译成this。
  在Javassist中,还会有一些其他具有特定含义的符号,这个我们在文章的最后统一说明。
  这段代码的效果如下所示。publicUser(){this。namebinghe;}
  接下来,就是调用CtClass的addConstructor()方法为User类添加无参构造方法。添加有参构造方法4。添加有参构造函数constructornewCtConstructor(newCtClass〔〕{pool。get(java。lang。String)},ctClass);constructor。setBody({0。name1;});ctClass。addConstructor(constructor);
  添加有参构造方法的整体流程和添加无参构造方法的整体流程相同,只是在创建CtConstructor对象时,在CtConstructor的构造方法的第一个参数类型数组中使用pool。get(java。lang。String)添加了一个数组元素,表示生成的目标类的构造方法存在一个String类型的参数。
  另外,在设置方法体时,使用了如下代码。0。name1;
  表示将构造方法的第一个参数赋值给成员变量name。这里,0表示this,1表示第一个参数,2表示第二个参数,以此类推。
  这段代码的效果如下所示。publicUser(Stringvar1){this。namevar1;}添加getset方法5。添加getter和setter方法ctClass。addMethod(CtNewMethod。setter(setName,param));ctClass。addMethod(CtNewMethod。getter(getName,param));
  添加getset方法就比较简单了,直接使用CtClass的addMethod()添加,使用CtNewMethod的setter()方法生成set方法,其中,第一个参数为生成的方法的名称setName,第二个参数表示是为哪个字段生成setName方法。
  使用CtNewMethod的getter()方法生成get()方法,第一个参数为生成的方法的名称getName,第二个参数表示是为哪个字段生成getName方法。
  这段代码的效果如下所示。publicvoidsetName(Stringvar1){this。namevar1;}publicStringgetName(){returnthis。name;}添加printName()方法6。创建一个输出name的方法CtMethodctMethodnewCtMethod(CtClass。voidType,printName,newCtClass〔〕{},ctClass);ctMethod。setModifiers(Modifier。PUBLIC);ctMethod。setBody({System。out。println(name);});ctClass。addMethod(ctMethod);
  添加printName()方法使用了Javassist中的CtMethod类,创建CtMethod类的对象时,第一个参数为方法的返回类型,第二个参数为方法的名称printName,第三个参数为方法的参数类型数组,第四个参数表示将生成的方法添加到哪个类。
  接下来,调用CtMethod的setModifiers()方法来设置printName()方法的访问修饰符,这里将其设置为public。紧接着为printName()方法设置方法体,在方法体中简单的在命令行打印成员变量name。
  最后通过CtClass的addMethod()方法将生成的printName方法添加到User类中。
  这段代码的效果如下所示。publicvoidprintName(){System。out。println(this。name);}完整案例
  为了方便小伙伴们更加清晰的看到完整的源代码,这里我也将完整的源代码贴出来,如下所示。authorbinghe(公众号:冰河技术)version1。0。0description使用Javassist生成一个User类,并测试publicclassCreateUserClass{使用Javassist创建一个User对象publicstaticvoidcreateUser()throwsException{使用默认的ClassPoolClassPoolpoolClassPool。getDefault();1。创建一个空类CtClassctClasspool。makeClass(io。binghe。bytecode。javassist。bean。User);2。新增一个字段privateStringname;字段的名称为nameCtFieldparamnewCtField(pool。get(java。lang。String),name,ctClass);设置访问修饰符为privateparam。setModifiers(Modifier。PRIVATE);设置字段的初始值为binghectClass。addField(param,CtField。Initializer。constant(binghe));3。添加无参的构造函数CtConstructorconstructornewCtConstructor(newCtClass〔〕{},ctClass);constructor。setBody({0。namebinghe;});ctClass。addConstructor(constructor);4。添加有参构造函数constructornewCtConstructor(newCtClass〔〕{pool。get(java。lang。String)},ctClass);constructor。setBody({0。name1;});ctClass。addConstructor(constructor);5。添加getter和setter方法ctClass。addMethod(CtNewMethod。setter(setName,param));ctClass。addMethod(CtNewMethod。getter(getName,param));6。创建一个输出name的方法CtMethodctMethodnewCtMethod(CtClass。voidType,printName,newCtClass〔〕{},ctClass);ctMethod。setModifiers(Modifier。PUBLIC);ctMethod。setBody({System。out。println(name);});ctClass。addMethod(ctMethod);ctClass。writeFile();}}效果演示
  编写main方法,直接调用CreateUserClass类的createUser()方法,如下所示。publicstaticvoidmain(String〔〕args)throwsException{CreateUserClass。createUser();}
  运行main()方法后,生成了我们想要的User类的字节码,如下所示。
  效果符合我们的预期。案例总结
  我们使用Javassist动态生成了符合预期的User类对象,通过本文的学习,我们掌握了如何使用Javassist生成JavaBean对象。是不是很简单呢?小伙伴们赶紧打开IDEA搞起来吧。

国内公认质量最好4款车很少修车我们都知道,随着私家车普及率的提升,汽车成为了人们日常生活最便捷的交通工具。获悉,一般人买车的时候,首先会把质量可靠性作为衡量的标准之一,毕竟,安全才是重中之重。不过,如今,车……家用车中的良心之作,每公里平均油耗仅3毛,全球拥有百万车主!导读:家用车中的良心之作,每公里平均油耗仅3毛,全球拥有百万车主!空间巨大的十万级家用车中,较为吃香的当属于紧凑级车型以及B级轿车领域。在潜力不错的紧凑级市场中,俨然成了……别老想着买老车!4月这4款新车将上市,款款有料,第1款续航7别老想着买老车!4月这4款新车将上市,款款有料,第1款续航700km说到买车,现在很多的朋友都喜欢看豪车,什么奔驰、宝马、奥迪、凯迪拉克、雷克萨斯什么的不管价格多少总之就……愚人节这天,丰田开的这个玩笑实在太蠢了甫于2019年2月18日、于菲律宾首演的丰田第6代Hiace车系。丰田亦在这敏感的4月1号愚人节当日,于澳洲官方媒体网站上,发表了以新一代Hiace车系为基础、所衍生的限量软顶……双离合和AT的差别有多大?老司机堵车十分钟你就知道了!珂健提醒:点击上方的蓝色小字珂健,或者微信搜索kejian121关注珂健的微信公众号,就可以第一时间收到珂健的图文推送了。每个工作日你都可以,到头条图文中感受珂健的汽车生活态度……北京市上海市重庆市天津市2022年5月楼市交易信息回顾过去的5月,楼市有点魔幻,楼市可谓是异常低迷,楼市冰冷。政策方面,房贷利率下调、LPR下降、公积金首套贷款额度提高。然而,客观来讲,政策对市场带来的作用,暂时还未显现出来。……英国农村的真实情况,如果用两个字来形容,那就是宁静印象中,我们并没有听说过多少关于英国的农村的事情,可能我们都不知道,英国的农村会是什么样子?又会和我们有什么不同?我们一起来看看吧。图为一个英国农村的农场里,有不少的牛羊。……只需三步解决卡顿!华为将为旧手机推出系统云翻新功能手机用的时间久了往往会出现卡顿问题,不少用户常常因此烦恼。近日,华为将为老旧手机推出系统云翻新功能,只需通过云备份数据、恢复出厂设置、云恢复数据,三步操作便可解决手机卡顿……国产又一7座SUV上市!比瑞虎8更大,1。6T有204马力,乘着国内SUV车型火热的东风,各家车企也是使出了浑身解数投放新产品加入市场。此时的车企投放产品就变得更有针对性,比如多功能、多座位、大空间这些吸引人眼球的产品定位就很好的迎合了……最实用的5个汽车配置,即使花钱也要装!现在的汽车变成了我们生活中实用的工具之一。随着一代又一代新型汽车的推出,汽车的功能性也得到了不断地优化。对于基本的标准配置,现在的车上一般都会配有。以下这些实用并且方便的配置,……汽车4万公里必须大保养,知道都更换啥吗?大家好,我是风子,我是一名汽车修理工。汽车保养、维修是我的日常工作。其实在我们修理工的眼里,没有什么大保养这个说法。我们做的都是熟人的车,讲究的是阶段性保养,在什么公里做什么样……阔别十年的汽车下乡政策又来了,最高补20000元!阔别十年汽车下乡政策再度启动多部门联合下发《进一步优化供给推动消费平稳增长促进形成强大国内市场的实施方案(2019)》其中关于汽车的相关政策有:……
王者荣耀铠的出装铭文很多人喜欢玩铠,那就说一下铠的铭文出装。铭文:10狩猎10鹰眼10祸源(追求暴效极限的话可以7祸源3无双)出装分为两套。一套打野全输出。一套半肉边路。打……保护脾胃,就是保护你的命根!一剂壮脾方,身体倍棒,吃嘛嘛香大家好,我是李医生!脾胃是个老生常谈的话题了,为什么总要说它呢,就是因为它实在太重要。都说五脏六腑亲兄弟,气血才是父母亲。气血从哪儿来呢,那就是我们的脾胃了。绕了一圈,最……二胎父母对子女的爱,为啥总是做不到一碗水端平?现在国家提倡生二胎三胎,很多大孩都会反对,但是大人都会说有了二胎爸爸妈妈还是会一样爱你的,我想问已经有二胎的家长和即将有二胎的家长,你们真的能做到平等对待吗?我就是出生8……远去的味道儿远去的味道儿活,就要够劲,还要够味。两天来,小雨时断时续,风吹树摇,黄叶满地,房子里也骤然冷了许多。我在衣柜里翻腾御冷的厚衣时,忽然想起不久前给去世的亲人送的寒衣。……王毅会见马尔代夫外长沙希德【王毅会见马尔代夫外长沙希德】当地时间2022年9月24日,国务委员兼外长王毅在纽约出席联合国大会期间会见马尔代夫外长沙希德。王毅祝贺沙希德担任联大主席期间成功履职,为联合国事……正式任命!62岁蔡振华走马电影推广大使,刘国梁支持,球迷激动大家好,我是詹妹,我们一起来关注国乒,目前国乒在卡塔尔的亚洲预选赛已经正式开赛,在新的周期也希望拿下好成绩,争取在2023年取得开门红。与此同时国乒也发生了重磅的好消息,我们退……美国政府把中国联通列入违规名单,吊销其在美经营权美国政府以国家安全理由将中国联通美洲公司列入违规名单,终止其在美国的经营授权。美国联邦通信委员会27日发布命令,吊销中国联通美洲营运有限公司(ChinaUnicom(Am……让你立刻清醒的文案1最后几天了,过年开始,我就要去喜欢能有结果和值得的人了2。不要愚蠢到拿时间长短来衡量感情。3。我会试着慢慢忘记这一切。然后擦干眼泪扎起高马尾从头再来。4。一……潘石屹这回真跑了,留下一个烂摊子焦点wumiancaijing。com潘氏夫妇这些年仅现金分红就拿到130多亿,而SOHO中国如今借款超160亿,打折卖项目度日。本文由无冕财经(wumiancaiji……先睹为快能横着走还能原地旋转,这款氢能概念车将亮相进博会【编者按】迈入第五个年头,中国国际进口博览会再度进入开幕倒计时。作为连接中国与世界的重要纽带,今年的四叶草展馆将迎来哪些全球尖端新品?八方来客又将为这场永不落幕的盛……科比坠机遗体照遭泄露案判决结果公布科比坠机遗体照遭泄露案判决结果公布,陪审团判给NBA巨星科比布莱恩特的遗孀1600万美元的赔偿金,原因是急救人员拍摄了2020年1月直升机坠毁现场并与公众分享的照片泄露。……中国财富报道数字人民币APP又更新了!新增两大功能,过年可以视频加载中。。。近日,数字人民币App再次完成版本更新,增加了专属头像、现金红包两大功能。其中,现金红包又包含现金红包、群红包和专属红包三类,分别可通过数字人民币App或……
友情链接:易事利快生活快传网聚热点七猫云快好知快百科中准网快好找文好找中准网快软网