您现在的位置是:首页 > 正文

java 动态创建类_Java运行时动态生成类几种方式

2024-02-01 04:50:24阅读 3

最近一个项目中利用规则引擎,提供用户拖拽式的灵活定义规则。这就要求根据数据库数据动态生成对象处理特定规则的逻辑。如果手写不仅每次都要修改代码,还要每次测试发版,而且无法灵活根据用户定义的规则动态处理逻辑。所以想到将公共逻辑写到父类实现,将特定逻辑根据字符串动态生成子类处理。这就可以一劳永逸解决这个问题。

那就着手从Java如何根据字符串模板在运行时动态生成对象。

Java是一门静态语言,通常,我们需要的class在编译的时候就已经生成了,为什么有时候我们还想在运行时动态生成class呢?

经过一番网上资料查找,由繁到简的方式总结如下:

一、利用JDK自带工具类实现

现在问题来了,动态生成字节码,难度有多大?

如果我们要自己直接输出二进制格式的字节码,在完成这个任务前,必须先认真阅读JVM规范第4章,详细了解class文件结构。估计读完规范后,两个月过去了。

所以,第一种方法,自己动手,从零开始创建字节码,理论上可行,实际上很难。

第二种方法,使用已有的一些能操作字节码的库,帮助我们创建class。

目前,能够操作字节码的开源库主要有CGLib和Javassist两种,它们都提供了比较高级的API来操作字节码,最后输出为class文件。

比如CGLib,典型的用法如下:

Enhancer e = newEnhancer();

e.setSuperclass(...);

e.setStrategy(newDefaultGeneratorStrategy() {protectedClassGenerator transform(ClassGenerator cg) {return newTransformingGenerator(cg,new AddPropertyTransformer(new String[]{ "foo"},newClass[] { Integer.TYPE }));

}});

Object obj= e.create();

比自己生成class要简单,但是,要学会它的API还是得花大量的时间,并且,上面的代码很难看懂对不对?

有木有更简单的方法?

有!

Java的编译器是javac,但是,在很早很早的时候,Java的编译器就已经用纯Java重写了,自己能编译自己,行业黑话叫“自举”。从Java 1.6开始,编译器接口正式放到JDK的公开API中,于是,我们不需要创建新的进程来调用javac,而是直接使用编译器API来编译源码。

使用起来也很简单:

JavaCompiler compiler =ToolProvider.getSystemJavaCompiler();int compilationResult = compiler.run(null, null, null, '/path/Test.java');

这么写编译是没啥问题,问题是我们在内存中创建了Java代码后,必须先写到文件,再编译,最后还要手动读取class文件内容并用一个ClassLoader加载。

有木有更简单的方法?

有!

其实Java编译器根本不关心源码的内容是从哪来的,你给它一个String当作源码,它就可以输出byte[]作为class的内容。

所以,我们需要参考Java Compiler API的文档,让Compiler直接在内存中完成编译,输出的class内容就是byte[]。

Mapresults;

JavaCompiler compiler=ToolProvider.getSyst

网站文章

  • antv图例出现分页_Echarts和highCharts图表使用总结(附AntV)

    Echarts:1.给y轴上间隔线设置成虚线yAxis: {type: 'value',boundaryGap: [0, '100%'],axisLine: {show...

    2024-02-01 04:49:54
  • 「NodeJs」nodejs 定时任务

    nodejs 定时访问网页。

    2024-02-01 04:49:47
  • std::forward()

    std::forward()完美转发。

    2024-02-01 04:49:38
  • freekan电影系统后台无法登录解决方法

    freekan电影系统后台无法登录解决方法

    这个freekan电影系统真的比较挑主机,不只是试了许多主机无法安装,有时安装上了明明账号密码正确还登录不上,但又找不到更好用的电影系统。幸亏我用的是老薛主机,售后非常给力,联系他们后立马就解决了,他...

    2024-02-01 04:49:32
  • SpringMvc+Mybatis +Oracle

    +Mybatis入门笔记http://www.cnblogs.com/hellokitty1/p/5216025.htmljsp运行原理JSP运行原理及运行过程https://blog.csdn.net/hanxuemin12345/article/details/23831645转载于:https://www.cnblogs.com/maowuyu-xb/p/9126367....

    2024-02-01 04:49:02
  • EasyExcel——自定义注解、实现动态获取下拉框内容

    EasyExcel——自定义注解、实现动态获取下拉框内容

    主要展示了在使用easyexcel导出过程中如何从数据库表获取动态下拉框内容,以及和固定下拉框内容的对比

    2024-02-01 04:48:56
  • Redis集群

    Redis集群

    Redis集群是一个提供在多个Redis节点间共享数据的程序集,可以支持多个Master。

    2024-02-01 04:48:50
  • 记一次生产环境GitLab服务和数据迁移到阿里云和GitLab版本升级

    记一次生产环境GitLab服务和数据迁移到阿里云和GitLab版本升级

    GitLab是一个用于管理代码的仓库系统,他是一个开源项目,使用Git作为代码管理工具,并在此基础上搭建起来的Web服务,可通过Web界面进行访问公开的或者私人项目。它拥有与Github类似的功能,能够浏览源代码,管理代码缺陷和注释。.........

    2024-02-01 04:48:20
  • SpringBoot整合Elasticsearch-elasticsearch-rest-high-level-client

    前言在前面几篇文章中演示ES安装时对外暴露有两个端口,一个是9200,一个是9300,这里9300是一个TCP端口,ES集群环境下也是通过9300端口通信的,是长连接的形式通信的,这里不推荐使用Spr...

    2024-02-01 04:48:13
  • Spring Boot 系统启动任务

    1. 背景 有时候我们会希望在Spring Boot项目启动时,完成一些初始化工作。 例如加载初始化的缓存信息,初始化一些系统运行的基本参数。 此时,就可以通过Spring Boot系统启动任务实现,...

    2024-02-01 04:48:05