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/

上一篇下一篇

猜你喜欢

热点阅读