如何在Java运行时生成和编译源


使用ClassFactory,可以在运行时生成类,但是如果我们只需要编译源代码而无需加载它们或仅生成源代码,该怎么办呢?

这是源代码生成器组件和Burningwave Core的JavaMemoryCompiler ,对我们有帮助。使用源代码生成器,我们可以生成源代码并将其存储在驱动器上,或者通过JavaMemoryCompiler对其进行编译。

现在,让我们尝试生成并存储以下类:

package source.generation.test;
import java.util.Arrays;
import java.util.List;
public class MyClass {


    private List<String> words;


    public MyClass(String... words) {
        this.words = Arrays.asList(words);
    }

    public void print() {
        System.out.print(String.join(" ", words));
    }

    public static void main(String[] args) {
        new MyClass(args).print();
    }
}

使用源代码生成器:

package source.generation.test;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.List;
import org.burningwave.core.classes.ClassSourceGenerator;
import org.burningwave.core.classes.FunctionSourceGenerator;
import org.burningwave.core.classes.GenericSourceGenerator;
import org.burningwave.core.classes.TypeDeclarationSourceGenerator;
import org.burningwave.core.classes.UnitSourceGenerator;
import org.burningwave.core.classes.VariableSourceGenerator;
public class SourceGenerationTester {



    public static UnitSourceGenerator generate() {
        return UnitSourceGenerator.create(SourceGenerationTester.class.getPackage().getName())
        .addClass(
            ClassSourceGenerator.create(TypeDeclarationSourceGenerator.create("MyClass"))
            .addField(
                VariableSourceGenerator.create(
                    TypeDeclarationSourceGenerator.create(List.class)
                    .addGeneric(GenericSourceGenerator.create(String.class)),
                    "words"
                )
            )
            .addConstructor(
                FunctionSourceGenerator.create().addParameter(
                    VariableSourceGenerator.create(
                        TypeDeclarationSourceGenerator.create(String.class)
                        .setAsVarArgs(true),
                        "words"
                    )
                ).addBodyCodeLine("this.words = Arrays.asList(words);").useType(Arrays.class)
            )
            .addMethod(
                FunctionSourceGenerator.create("print")
                .addModifier(Modifier.PUBLIC).setReturnType(void.class)
                .addBodyCodeLine(
                  "System.out.println(\"\\n\\t\" + String.join(\" \", words) + \"\\n\");"
                )
            )
            .addMethod(
                FunctionSourceGenerator.create("main")
                .addModifier(Modifier.PUBLIC | Modifier.STATIC)
                .setReturnType(void.class)
                .addParameter(VariableSourceGenerator.create(String[].class, "args"))
                .addBodyCodeLine("new MyClass(args).print();")
            )
        );
    }


    public static void main(String[] args) {
        UnitSourceGenerator unitSG = SourceGenerationTester.generate();
        unitSG.storeToClassPath(System.getProperty("user.home") + "/Desktop/sources");
        System.out.println("\nGenerated code:\n" + unitSG);
    }
}

现在,让我们尝试编译源代码,并使用JavaMemoryCompiler存储编译后的文件:

package source.compilation.test;
import org.burningwave.core.assembler.ComponentContainer;
import org.burningwave.core.classes.JavaMemoryCompiler;
import org.burningwave.core.classes.JavaMemoryCompiler.Compilation;
import org.burningwave.core.concurrent.QueuedTasksExecutor.ProducerTask;
import org.burningwave.core.io.FileSystemItem;
import source.generation.test.SourceGenerationTester;
public class SourceCompilationTester {

    public static void main(String[] args) throws ClassNotFoundException {

        ComponentContainer componentContainer = ComponentContainer.getInstance();
        JavaMemoryCompiler javaMemoryCompiler = componentContainer.getJavaMemoryCompiler();
        ProducerTask<Compilation.Result> compilationTask = javaMemoryCompiler.compile(
            Compilation.Config.forUnitSourceGenerator(
                SourceGenerationTester.generate()
            )
            .storeCompiledClassesTo(
                System.getProperty("user.home") + "/Desktop/classes"
            )
        );

        Compilation.Result compilationResult = compilationTask.join();

        System.out.println("\n\tAbsolute path of compiled file: " + 
            compilationResult.getClassPath()
            .findFirstInAllChildren(
                FileSystemItem.Criteria.forAllFileThat(FileSystemItem::isFile)
            ).getAbsolutePath() + "\n"
        );
    }

}

现在让我们尝试加载已编译的文件:

package source.compilation.test;
import static org.burningwave.core.assembler.StaticComponentContainer.ClassLoaders;
import static org.burningwave.core.assembler.StaticComponentContainer.Methods;
import org.burningwave.core.assembler.ComponentContainer;
import org.burningwave.core.classes.JavaMemoryCompiler;
import org.burningwave.core.classes.JavaMemoryCompiler.Compilation;
import org.burningwave.core.concurrent.QueuedTasksExecutor.ProducerTask;
import source.generation.test.SourceGenerationTester;
public class SourceCompilationTester {


    public static void main(String[] args) throws ClassNotFoundException {
        ComponentContainer componentContainer = ComponentContainer.getInstance();
        JavaMemoryCompiler javaMemoryCompiler = componentContainer.getJavaMemoryCompiler();
        ProducerTask<Compilation.Result> compilationTask = javaMemoryCompiler.compile(
            Compilation.Config.forUnitSourceGenerator(
                SourceGenerationTester.generate()
            )
            .storeCompiledClassesTo(
                System.getProperty("user.home") + "/Desktop/classes"
            )
        );


        Compilation.Result compilattionResult = compilationTask.join();


        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        ClassLoaders.addClassPaths(classLoader, compilattionResult.getDependencies());
        ClassLoaders.addClassPath(classLoader, compilattionResult.getClassPath().getAbsolutePath());
        Class<?> cls = classLoader.loadClass("source.generation.test.MyClass");
        Methods.invokeStaticDirect(cls, "main", new Object[] {new String[] {"Hello", "world!"}});
    }

}


原文链接:http://codingdict.com