基于javassist进行动态编程过程解析

作者:玄同太子 时间:2021-12-03 07:23: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>

来源:https://www.cnblogs.com/zhi-leaf/p/10480913.html

标签:java,ssist,动态,编程
0
投稿

猜你喜欢

  • android图片处理之让图片变成圆形

    2021-08-01 00:29:53
  • springboot集成redis并使用redis生成全局唯一索引ID

    2023-11-28 05:42:39
  • android通过拼音搜索中文的功能实现代码

    2022-03-12 04:48:17
  • 基于C语言的库封装发布技术详解

    2023-10-14 05:58:46
  • SpringBoot实现多个子域共享cookie的示例

    2021-08-02 17:56:47
  • c#读写注册表示例分享

    2022-06-26 13:08:45
  • java高并发ScheduledThreadPoolExecutor与Timer区别

    2023-08-11 03:08:29
  • 配合Swagger使用绝佳的两款直观易用JSON可视化工具

    2021-10-14 23:50:23
  • C#如何将DLL打包到程序中

    2022-08-06 13:18:57
  • Kotlin标准函数与静态方法应用详解

    2022-01-21 10:45:33
  • java模拟实现双向链表

    2022-06-05 09:16:16
  • java反射获取和调用方法

    2021-11-23 11:05:02
  • Java实现简单的扫雷小程序

    2022-11-18 02:14:07
  • Java中volatile关键字的作用

    2023-06-02 17:02:55
  • IDEA类与方法注释模板设置图文教程(非常详细)

    2022-02-24 10:18:29
  • 自定义一个异常类模板的简单实例

    2022-04-30 02:53:14
  • Java实现简单的万年历

    2023-11-29 08:31:24
  • Java模拟多线程实现抢票代码实例

    2022-11-17 07:41:51
  • SpringBoot使用prometheus监控的示例代码

    2021-05-29 02:37:41
  • flutter Bloc 实现原理示例解析

    2023-07-18 08:00:39
  • asp之家 软件编程 m.aspxhome.com