Java 运行时动态将源代码生成类 并执行
2023-05-09 本文已影响0人
zxbyh
就相当于可以吧java代码当脚本语言来用. 在特定的场景下还是有必要的!
添加pom依赖
<!--groovy-->
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy</artifactId>
<version>3.0.16</version>
</dependency>
新建一个抽象类 Person
package com.yourcom.tool.base.obj;
import lombok.Data;
@Data
public abstract class Person {
private String name;
public abstract void sayHello();
}
接下来要演示 通过代码的字符串 动态 继承这个Persion,然后调用它的方法. 直接上代码
package cn.quick.base.obj;
import cn.hutool.core.date.DateUtil;
import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyObject;
import groovy.lang.GroovyShell;
import java.io.File;
import java.util.concurrent.ConcurrentHashMap;
public class CompilerUtil {
private static ConcurrentHashMap<String, Class> _clazzRecordConcurrentHashMap = new ConcurrentHashMap<>();
public static Class generateClass(String javaFilename, String javaCode ,Boolean renew) throws Exception {
if(renew) {
System.out.println("nnnn!!");
_clazzRecordConcurrentHashMap.put(javaFilename, (new GroovyClassLoader()).parseClass(javaCode));
}
else {
_clazzRecordConcurrentHashMap.computeIfAbsent(javaFilename, k->{
System.out.println("rrrr!!");
return (new GroovyClassLoader()).parseClass(javaCode);
});
}
return _clazzRecordConcurrentHashMap.get(javaFilename);
}
public static void runClassDm(String name,boolean renew) throws Exception {
Person person = (Person)generateClass(
"com.yourcom.tool.base.obj.Teacher",
"""
package com.yourcom.tool.base.obj
public class Teacher extends Person {
@Override
public void sayHello() {
System.out.println("My name is " + getName() + ", I am a teacher");
}
}
""",
renew
).newInstance();
person.setName(name);
person.sayHello();
}
public static void runScript(){
GroovyShell groovyShell = new GroovyShell();
//执行Groovy脚本.
groovyShell.evaluate("println \"hello world\"");
//执行java 脚本.
groovyShell.evaluate("System.out.println(\"hello groovyShell\");");
}
public static void runClassFromFile() throws Exception {
GroovyClassLoader loader = new GroovyClassLoader();
Class groovyClass = loader.parseClass(new File("D:\\workspace\\rad-solution\\quick-all\\quick-base\\src\\main\\java\\cn\\quick\\base\\obj\\Student.java")); // 也可以解析字符串
GroovyObject groovyObject = (GroovyObject) groovyClass.newInstance();
groovyObject.invokeMethod("say", "helloWorld");
}
public static void main(String[] args) throws Exception {
runScript();
runClassFromFile();
Long bgn = DateUtil.current();
runClassDm("Tom",false);
System.out.println(DateUtil.current() - bgn);
runClassDm("Make",false);
System.out.println(DateUtil.current() - bgn);
runClassDm("white",true);
System.out.println(DateUtil.current() - bgn);
}
}
然后运行这个例子,效果如下
hello world
hello groovyShell
student say helloWorld
rrrr!!
My name is Tom, I am a teacher
20
My name is Make, I am a teacher
20
nnnn!!
My name is white, I am a teacher
37
这个的就是用了 Groovy 中的 GroovyClassLoader
关于 Groovy 更多的介绍 见
https://www.jianshu.com/p/2c6b95097b2c
https://www.bilibili.com/video/BV1xF411P7w5/