时间:2021-05-19
今天在研究dubbo时,发现一个新的知识点,可以使用javassist包进行动态编程,hibernate也使用该包进行编程。晚上百度了很多资料,将它的特性以代码的形式展现出来。
package com.zhi.demo;import java.lang.reflect.Field;import javassist.ClassPool;import javassist.CtClass;import javassist.CtConstructor;import javassist.CtField;import javassist.CtMethod;import javassist.CtNewConstructor;import javassist.CtNewMethod;import javassist.Loader;import javassist.Modifier;import javassist.bytecode.AccessFlag;/** * Javassist动态编程测试 * * @date 2019年03月11日23:00:33 * */public class JavassistTest { public static void main(String[] args) { try { test(); } catch (Exception e) { e.printStackTrace(); } } private static void test() throws Exception { System.out.println("-------------------新增类------------------"); ClassPool pool = ClassPool.getDefault(); // 创建类 CtClass ct = pool.makeClass("com.zhi.Person"); // 让类实现Cloneable接口 ct.setInterfaces(new CtClass[] { pool.makeInterface("java.lang.Cloneable") }); // 添加一个int类型的共有属性 CtField fieldId = new CtField(CtClass.intType, "id", ct); fieldId.setModifiers(AccessFlag.PUBLIC); ct.addField(fieldId); // 添加一个默认构造器 CtConstructor constructor1 = CtNewConstructor.make("public Person(){this.id=1;}", ct); ct.addConstructor(constructor1); // 添加方法 CtMethod helloM = CtNewMethod .make("public void hello(String des){System.out.println(\"执行hello方法,\"+des+\",我的id是\"+this.id);}", ct); ct.addMethod(helloM); // 将生成的.class文件保存到磁盘 ct.writeFile(); // 加载目标类,可用ct.toClass()或new Loader(pool).loadClass() Class<?> clazz = ct.toClass();// Class<?> clazz = new Loader(pool).loadClass("com.zhi.Person"); // 输出类基本信息 System.out.println("包名:" + clazz.getPackageName()); System.out.println("类名:" + clazz.getName()); System.out.println("简要类名:" + clazz.getSimpleName()); System.out.println("限定符:" + Modifier.toString(clazz.getModifiers())); System.out.println("继承类:" + clazz.getSuperclass().getName()); Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { System.out.println("属性名称:" + field.getName() + ",属性类型:" + field.getType() + ",限定符:" + Modifier.toString(field.getModifiers())); } // 构造一个对象,并执行hello方法 Object ob = clazz.getDeclaredConstructor().newInstance(); clazz.getMethod("hello", String.class).invoke(ob, "张三"); // 解冻(执行toClass后会自动冻结) ct.defrost(); System.out.println("-------------------修改类------------------"); // 添加一个String类型的私有属性 CtField fieldName = new CtField(pool.get(String.class.getName()), "name", ct); fieldName.setModifiers(AccessFlag.PRIVATE); ct.addField(fieldName); // 添加带参的构造函数 CtConstructor constructor2 = new CtConstructor(new CtClass[] { pool.get(String.class.getName()) }, ct); constructor2.setModifiers(Modifier.PUBLIC); constructor2.setBody("{this.name=$1;}"); ct.addConstructor(constructor2); ct.addMethod(CtNewMethod.make("public void setName(String name){this.name=name;}", ct)); ct.addMethod(CtNewMethod.make("public String getName(){return this.name;}", ct)); ct.writeFile(); // 加载类,若前面已用ct.toClass()进行加载,则这里不能再用ct.toClass()加载,否则会出错,同一个加载不能2次加载同一个类 clazz = new Loader(pool).loadClass("com.zhi.Person"); fields = clazz.getDeclaredFields(); for (Field field : fields) { System.out.println("属性名称:" + field.getName() + ",属性类型:" + field.getType() + ",限定符:" + Modifier.toString(field.getModifiers())); } ob = clazz.getDeclaredConstructor(String.class).newInstance("马云"); System.out.println("执行getName方法得到的值为:" + clazz.getMethod("getName").invoke(ob)); }}执行上面代码输出结果为:
-------------------新增类------------------包名:com.zhi类名:com.zhi.Person简要类名:Person限定符:public继承类:java.lang.Object属性名称:id,属性类型:int,限定符:public执行hello方法,张三,我的id是1-------------------修改类------------------属性名称:id,属性类型:int,限定符:public属性名称:name,属性类型:class java.lang.String,限定符:private执行getName方法得到的值为:马云说明:
$0,$1,$2:分别代表this,第一个参数,第二个参数
$r:方法返回值的类型。
$_:方法返回值
依赖包
<dependency> <groupId>org.javassist</groupId> <artifactId>javassist</artifactId> <version>3.24.1-GA</version></dependency>以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
大家在上网的时候,都需要有一个ip地址,而现在很多人都在使用动态ip,这时候便需要进行动态ip解析了。下面就给大家介绍动态ip是什么意思,为什么要进行域名动态i
所谓动态折线图,就是折线图能随着手指的滑动进行动态绘制,这里很定会产生动画效果。基于这个效果,这里使用SurfaceView进行制图。实现步奏如下:(1):这里
1、C++中的动态内存分配通过new关键字进行动态内存申请C++中的动态内存申请时基于类型进行的delete关键用于内存释放C语言其实是不支持动态内存分配的,是
1:Ajax技术包含以下几点:基于Web标准(XHTML+CSS)的展示使用DOM进行动态显示和交互使用XMLHttpRequest进行数据交换和相关操作使用j
JavaScript是一种描述型脚本语言,它不同于java或C#等编译性语言,它不需要进行编译成中间语言,而是由浏览器进行动态地解析与执行。如果你不能理解jav