使用javax.tools.JavaCompiler根据字符串内容动态生成新的Java类并编译成.class

简介: 使用javax.tools.JavaCompiler根据字符串内容动态生成新的Java类并编译成.class

测试代码:

package dynamicproxy;
public class DynamicProxy implements IHelloWorld
{
  IHelloWorld helloWorld;
  public DynamicProxy(IHelloWorld helloWorld)
  {
    this.helloWorld = helloWorld;
  }
  public void print()
  {
    System.out.println("Before Hello World!");
    helloWorld.print();
    System.out.println("After Hello World!");
  }
}
package dynamicproxy;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Serializable;
import java.io.Writer;
import java.lang.reflect.Constructor;
import java.net.URL;
import java.net.URLClassLoader;
import javax.tools.JavaCompiler;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
class HelloWorldImp implements IHelloWorld {
  public void print() {
    System.out.println("Hello World");
  }
}
public class DynamicProxyDemo implements Serializable {
  private static final long serialVersionUID = 1L;
  public static void main(String[] arg) throws Exception {
    Class<?> c = getProxyClass();
    Constructor<?> constructor = c.getConstructor(IHelloWorld.class);
    IHelloWorld helloWorldImpl = new HelloWorldImp();
    IHelloWorld helloWorld = (IHelloWorld) constructor.newInstance(helloWorldImpl);
    helloWorld.print();
  }
  private static String getSourceCode() {
    String src = "package dynamicproxy;\n\n"
        + "public class DynamicProxy implements IHelloWorld\n" + "{\n"
        + "\tIHelloWorld helloWorld;\n\n"
        + "\tpublic DynamicProxy(IHelloWorld helloWorld)\n" + "\t{\n"
        + "\t\tthis.helloWorld = helloWorld;\n" + "\t}\n\n"
        + "\tpublic void print()\n" + "\t{\n"
        + "\t\tSystem.out.println(\"Before Hello World!\");\n"
        + "\t\thelloWorld.print();\n"
        + "\t\tSystem.out.println(\"After Hello World!\");\n" + "\t}\n"
        + "}";
    return src;
  }
  private static String createJavaFile(String sourceCode) {
    String fileName = "C:\\Users\\i042416\\git\\JavaTwoPlusTwoEquals5\\src\\dynamicproxy\\DynamicProxy.java";
    File javaFile = new File(fileName);
    Writer writer;
    try {
      writer = new FileWriter(javaFile);
      writer.write(sourceCode);
      writer.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
    return fileName;
  }
  private static void compile(String fileName) {
    try {
      JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
      StandardJavaFileManager sjfm = compiler.getStandardFileManager(null, null, null);
      Iterable<? extends JavaFileObject> iter = sjfm.getJavaFileObjects(fileName);
      CompilationTask ct = compiler.getTask(null, sjfm, null, null, null, iter);
      ct.call();
      sjfm.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
  private static Class<?> loadClass() {
    URL[] urls;
    Class<?> c = null;
    try {
      urls = new URL[] { (new URL("file:\\"
          + "C:\\Users\\i042416\\git\\JavaTwoPlusTwoEquals5\\src\\")) };
      URLClassLoader ul = new URLClassLoader(urls);
      c = ul.loadClass("dynamicproxy.DynamicProxy");
      System.out.println("Class loaded successfully: " + c.getName());
      ul.close();
    } catch (ClassNotFoundException | IOException e) {
      e.printStackTrace();
    }
    return c;
  }
  private static Class<?> getProxyClass() {
    String sourceCode = getSourceCode();
    String javaFile = createJavaFile(sourceCode);
    compile(javaFile);
    return loadClass();
  }
}
package dynamicproxy;
import java.io.File;
import java.io.FileWriter;
import java.io.Serializable;
import java.io.Writer;
import java.lang.reflect.Constructor;
import java.net.URL;
import java.net.URLClassLoader;
import javax.tools.JavaCompiler;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
interface HelloWorld
{
    void print();
}
class HelloWorldImpl implements HelloWorld
{
    public void print()
    {
        System.out.println("Hello World");
    }
}
public class DynamicProxyTest implements Serializable
{
    private static final long serialVersionUID = 1L;
    private static void test() throws Exception{
      long start = System.currentTimeMillis();
        HelloWorld helloWorld = (HelloWorld) newProxyInstance();
        System.out.println("动态生成代理耗时:" + (System.currentTimeMillis() - start) + "ms");
        helloWorld.print();
        System.out.println();
    }
    public static void main(String[] arg) throws Exception{
      test();
    }
    public static Object newProxyInstance() throws Exception
    {
        String src = "package dynamicproxy;\n\n" + 
                     "public class StaticProxy implements HelloWorld\n" + 
                     "{\n" + 
                     "\tHelloWorld helloWorld;\n\n" + 
                     "\tpublic StaticProxy(HelloWorld helloWorld)\n" + 
                     "\t{\n" + 
                     "\t\tthis.helloWorld = helloWorld;\n" + 
                     "\t}\n\n" + 
                     "\tpublic void print()\n" + 
                     "\t{\n" + 
                     "\t\tSystem.out.println(\"Before Hello World!\");\n" + 
                     "\t\thelloWorld.print();\n" + 
                     "\t\tSystem.out.println(\"After Hello World!\");\n" + 
                     "\t}\n" + 
                     "}";
        /** 生成一段Java代码 */
        String fileDir = System.getProperty("user.dir");
        String fileName = "C:\\Users\\i042416\\git\\JavaTwoPlusTwoEquals5\\src\\dynamicproxy\\StaticProxyDemo.java";
        File javaFile = new File(fileName);
        Writer writer = new FileWriter(javaFile);
        writer.write(src);
        writer.close();
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        StandardJavaFileManager sjfm = compiler.getStandardFileManager(null, null, null);
        Iterable<? extends JavaFileObject> iter = sjfm.getJavaFileObjects(fileName);
        CompilationTask ct = compiler.getTask(null, sjfm, null, null, null, iter);
        ct.call();
        sjfm.close();
        URL[] urls = new URL[] {(new URL("file:\\" + "C:\\Users\\i042416\\git\\JavaTwoPlusTwoEquals5\\dynamicproxy\\src"))};
        URLClassLoader ul = new URLClassLoader(urls);
        System.out.println("class loader for url");
        Class<?> c = ul.loadClass("dynamicproxy.StaticProxy");
        Constructor<?> constructor = c.getConstructor(HelloWorld.class);
        HelloWorld helloWorldImpl = new HelloWorldImpl();
        HelloWorld helloWorld = (HelloWorld)constructor.newInstance(helloWorldImpl);
        File classFile = new File(fileDir + "\\src\\com\\xrq\\proxy\\StaticProxy.class");
        javaFile.delete();
        classFile.delete();
        ul.close();
        return helloWorld;
    }
}
package dynamicproxy;
public interface IHelloWorld
{
    void print();
}
相关文章
|
17天前
|
Java
Java 字符串分割split空字符串丢失解决方案
Java 字符串分割split空字符串丢失解决方案
|
4天前
|
Java 关系型数据库 MySQL
Elasticsearch【问题记录 01】启动服务&停止服务的2类方法【及 java.nio.file.AccessDeniedException: xx/pid 问题解决】(含shell脚本文件)
【4月更文挑战第12天】Elasticsearch【问题记录 01】启动服务&停止服务的2类方法【及 java.nio.file.AccessDeniedException: xx/pid 问题解决】(含shell脚本文件)
30 3
|
19小时前
|
Java 索引
【java基础】字符串String的基本处理集锦
【java基础】字符串String的基本处理集锦
11 0
|
21小时前
|
人工智能 安全 Java
Java8 - LocalDateTime时间日期类使用详解
Java8 - LocalDateTime时间日期类使用详解
|
2天前
|
安全 Java 程序员
|
2天前
|
Java
Java Class类
Java Class类
8 0
|
9天前
|
Java 编译器
Java Character 类
4月更文挑战第13天
|
10天前
|
存储 Java
Java基础教程(7)-Java中的面向对象和类
【4月更文挑战第7天】Java是面向对象编程(OOP)语言,强调将事务抽象成对象。面向对象与面向过程的区别在于,前者通过对象间的交互解决问题,后者按步骤顺序执行。类是对象的模板,对象是类的实例。创建类使用`class`关键字,对象通过`new`运算符动态分配内存。方法包括构造函数和一般方法,构造函数用于对象初始化,一般方法处理逻辑。方法可以有0个或多个参数,可变参数用`类型...`定义。`this`关键字用于访问当前对象的属性。
|
13天前
|
Java Shell
Java 21颠覆传统:未命名类与实例Main方法的编码变革
Java 21颠覆传统:未命名类与实例Main方法的编码变革
13 0
|
13天前
|
Java
Java 15 神秘登场:隐藏类解析未知领域
Java 15 神秘登场:隐藏类解析未知领域
17 0