Generating classes at runtime and invoking their methods with and without the use of Reflection in Java

Tutorials (13 Part Series)

1 How to create your own dependency injection framework in Java
2 How to find all the classes of a package in Java
9 more parts…
3 How to get field values with Reflection and with direct memory access in Java
4 Optimizing CPU usage by performing tasks in parallel with different priorities in Java
5 How to bind methods or constructors to functional interfaces in Java
6 Generating classes at runtime and invoking their methods with and without the use of Reflection in Java
7 A fast and flexible way to scan the class paths in Java
8 Executing stringified source code in Java
9 How to scan the file system in Java
10 Invoking and handling privates and all other methods of an object with and without the use of Reflection in Java
11 Making applications created with old Java versions work on Java 9 and later versions
12 How to generate and compile sources at runtime in Java
13 Iterating collections and arrays in parallel by setting thread priority

The generation of classes at runtime is an advanced topic that requires a lot of knowledge that can be reduced if you use particular libraries that perform the most complex functions to accomplish this task.
So, for this purpose, we can use the ClassFactory component and the sources generating components of the Burningwave Core library by adding to our pom.xml the following dependency:

After this we set the code to be generated in
UnitSourceGenerator objects and we must pass it to
loadOrBuildAndDefine method of ClassFactory with the ClassLoader where you want to define newly generated classes.

This method performs the following operations: tries to load all the classes present in the UnitSourceGenerator through the class loader, if at least one of these is not found it proceeds to compile all the UnitSourceGenerators and uploading their classes on class loader: in this case, keep in mind that if a class with the same name was previously loaded by the class loader, the compiled class will not be uploaded. If you need more information you can:

Once the classes have been compiled and loaded, it is possible to invoke their methods in severals ways as shown at the end of the example below.

UnitSourceGenerator unitSG = UnitSourceGenerator.create("packagename").addClass(
    ClassSourceGenerator.create(
        TypeDeclarationSourceGenerator.create("MyExtendedClass")
    ).addModifier(
        Modifier.PUBLIC
    //generating new method that override MyInterface.convert(LocalDateTime)
    ).addMethod(
        FunctionSourceGenerator.create("convert")
        .setReturnType(
            TypeDeclarationSourceGenerator.create(Comparable.class)
            .addGeneric(GenericSourceGenerator.create(Date.class))
        ).addParameter(VariableSourceGenerator.create(LocalDateTime.class, "localDateTime"))
        .addModifier(Modifier.PUBLIC)
        .addAnnotation(AnnotationSourceGenerator.create(Override.class))
        .addBodyCodeLine("return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());")
        .useType(ZoneId.class)
    ).addConcretizedType(
        MyInterface.class
    ).expands(ToBeExtended.class)
);
System.out.println("\nGenerated code:\n" + unitSG.make());
//With this we store the generated source to a path
unitSG.storeToClassPath(System.getProperty("user.home") + "/Desktop/bw-tests");
ComponentSupplier componentSupplier = ComponentContainer.getInstance();
ClassFactory classFactory = componentSupplier.getClassFactory();
//this method compile all compilation units and upload the generated classes to default
//class loader declared with property "class-factory.default-class-loader" in 
//burningwave.properties file (see "Overview and configuration").
//If you need to upload the class to another class loader use
//loadOrBuildAndDefine(LoadOrBuildAndDefineConfig) method
ClassFactory.ClassRetriever classRetriever = classFactory.loadOrBuildAndDefine(
    unitSG
);
Class<?> generatedClass = classRetriever.get(
    "packagename.MyExtendedClass"
);
ToBeExtended generatedClassObject =
    Constructors.newInstanceOf(generatedClass);
generatedClassObject.printSomeThing();
System.out.println(
    ((MyInterface)generatedClassObject).convert(LocalDateTime.now()).toString()
);
//You can also invoke methods by casting to Virtual (an interface offered by the
//library for faciliate use of runtime generated classes)
Virtual virtualObject = (Virtual)generatedClassObject;
//Invoke by using reflection
virtualObject.invoke("printSomeThing");
//Invoke by using MethodHandle
virtualObject.invokeDirect("printSomeThing");
System.out.println(
    ((Date)virtualObject.invokeDirect("convert", LocalDateTime.now())).toString()
);
classRetriever.close();

Enter fullscreen mode Exit fullscreen mode

In this short article we have learned how to generate classes at runtime in Java, how to load them and create instances; the complete source is available at this at this page.

Tutorials (13 Part Series)

1 How to create your own dependency injection framework in Java
2 How to find all the classes of a package in Java
9 more parts…
3 How to get field values with Reflection and with direct memory access in Java
4 Optimizing CPU usage by performing tasks in parallel with different priorities in Java
5 How to bind methods or constructors to functional interfaces in Java
6 Generating classes at runtime and invoking their methods with and without the use of Reflection in Java
7 A fast and flexible way to scan the class paths in Java
8 Executing stringified source code in Java
9 How to scan the file system in Java
10 Invoking and handling privates and all other methods of an object with and without the use of Reflection in Java
11 Making applications created with old Java versions work on Java 9 and later versions
12 How to generate and compile sources at runtime in Java
13 Iterating collections and arrays in parallel by setting thread priority

原文链接:Generating classes at runtime and invoking their methods with and without the use of Reflection in Java

© 版权声明
THE END
喜欢就支持一下吧
点赞6 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容