背景:自动生成代码的一个小工具中要通过创建一个Service.java源文件,然后对该源文件进行编译生成对应的class文件,之后通过反射调用Service.java的所有声明方法。自动生成的代码的功能是对每个Service.java的方法进行对应的case和data的自动生成。
步骤:
- 拷贝java文件:将子模块中的Service.java拷贝到common包的代码生成目录
- 编译java文件:通过动态编译工具进行文件编译
- 反射调用:调用Service.class的getDecalaredMethods()方法
- 生成data、case文件:
动态编译代码:
public static void compile(String sourceFilePath, String classPath) throws IOException {
//编译java文件
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
Iterable sourcefiles = fileManager.getJavaFileObjects(sourceFilePath);
//指定编译文件存放位置,如果不指定的话,编译的文件会和java源文件在一个文件夹中
//这样的话加载类的时候会报java.lang.ClassNotFoundException
Iterable<String> options = Arrays.asList("-d", classPath);
compiler.getTask(null, fileManager, null, options, null, sourcefiles).call();
fileManager.close();
}
拷贝文件代码:
private static void generateServiceInterface(String sourceServicePath) throws IOException {
File file = new File(sourceServicePath);
String absoluteUtilServicePath = getAbsoluteUtilServicePath();
File targetServiceFile = new File(absoluteUtilServicePath);
targetServiceFile.delete();
String packageLine = "package codeGenerator;";
String oldPackageLine = "package";
if (targetServiceFile.exists()) {
targetServiceFile.delete();
}
Files.touch(targetServiceFile);
List<String> strings = Files.readLines(file, Charsets.UTF_8);
StringBuilder sourceCode = new StringBuilder();
for (String string : strings) {
if (string.contains(oldPackageLine)) {
string = packageLine;
}
sourceCode.append(string);
sourceCode.append(lineSeparator);
}
FileWriter fileWriter = new FileWriter(targetServiceFile);
PrintWriter printWriter = new PrintWriter(fileWriter);
printWriter.write(sourceCode.toString());
printWriter.close();
CompilerAPI.compile(absoluteUtilServicePath, classPath);
}