有个spring-boot项目需要用到spoon对java项目代码进行解析,从而获取一些信息。实际开发过程中,发现使用mvn spring-boot:run
能够正常运行,但打成包之后,使用java -jar
能够启动项目,但部分文件无法解析。
出错代码
使用的是官方示例,修改的代码。
public static void parse(String code){
CtClass classContent = Launcher.parseClass(code);
classContent.getAnnotations().stream().forEach(a ->{
//do somthing;
});
}
项目中需要解析代码中的注解。发现使用java -jar
运行时,某些通过.*
导入的注解会出现解析失败。该项通过,在源代码中二次显式导入需要解析的注解解决。但之后又发现注解参数中使用的导入的枚举类型也会报错。
解决方案
mvn spring-boot:run
与java -jar
最大的区别是classpath。出现这种错误是因为,Launcher.parseClass(code)
没有正确导入依赖。修改源代码parseClass方法,手动注入需要解析的注解所在的包。
public static CtClass<?> customParseClass(String code) {
Launcher launcher = new Launcher();
launcher.addInputResource(new VirtualFile(code));
//
launcher.getEnvironment().setSourceClasspath(new String[]{"target/example-project/WEB-INF/lib/需要解析注解所在的包.RELEASE.jar"});
launcher.getEnvironment().setAutoImports(true);
Collection<CtType<?>> allTypes = launcher.buildModel().getAllTypes();
if (allTypes.size() != 1) {
throw new SpoonException("parseClass only considers one class. Please consider using a Launcher object for more advanced usage.");
}
try {
return (CtClass<?>) allTypes.stream().findFirst().get();
} catch (ClassCastException e) {
throw new SpoonException("parseClass only considers classes (and not interfaces and enums). Please consider using a Launcher object for more advanced usage.");
}
}
打包成docker 镜像时,将依赖包也放到相对路径下。