用于生成 Java 源文件的 JavaAPI

我正在寻找一个框架来生成 Java 源文件。

类似于下面的 API:

X clazz = Something.createClass("package name", "class name");
clazz.addSuperInterface("interface name");
clazz.addMethod("method name", returnType, argumentTypes, ...);


File targetDir = ...;
clazz.generate(targetDir);

然后,应该在目标目录的子目录中找到一个 java 源文件。

有人知道这样一个框架吗?


编辑:

  1. 我真的需要源文件。
  2. 我还想填写方法的代码。
  3. 我正在寻找一个高级抽象,而不是直接的字节码操作/生成。
  4. 我还需要对象树中的“类的结构”。
  5. 问题领域是通用的: 生成大量非常不同的类,没有“公共结构”。

解决方案
我已经张贴了2个答案基于你的答案... 使用 CodeModel使用 Eclipse JDT

我在我的解决方案中使用了 代码模型,: -)

56304 次浏览

如果你真的需要源代码,我不知道任何生成源代码的东西。但是,可以使用 ASMCGLIB直接创建。类文件。

您也许可以从这些文件中生成源代码,但是我只使用它们来生成字节码。

Eclipse JET项目可以用来生成源代码。我不认为它的 API 和你描述的完全一样,但是每次我听说一个项目做 Java 源代码生成,他们都使用 JET 或者自己开发的工具。

我是为了模拟生成器工具自己做的。这是一个非常简单的任务,即使您需要遵循 Sun 格式化指南。我敢打赌,你完成代码的速度会比你在互联网上找到的东西更快,更符合你的目标。

你已经基本上概述了你自己的 API。现在只需要用实际的代码来填充它!

另一种选择是 Eclipse JDT 的 AST,如果您需要重写任意的 Java 源代码而不仅仅是生成源代码,那么它是很好的选择。 (我相信它可以独立于 Eclipse 使用)。

不知道有没有库,但是您可能只需要一个通用模板引擎。有 很多,我个人有很好的经验与 FreeMarker

Sun 提供了一个名为 CodeModel 的 API,用于使用 API 生成 Java 源文件。这不是一件容易获得信息的事情,但它在那里,它工作得非常好。

获得它的最简单方法是作为 JAXB 2 RI 的一部分—— XJC schema-to-java 生成器使用 CodeModel 生成其 java 源代码,并且它是 XJC jar 的一部分。您可以只对 CodeModel 使用它。

http://codemodel.java.net/拿过来

使用 CodeModel 找到的解决方案
谢谢 Skaffman

例如,使用以下代码:

JCodeModel cm = new JCodeModel();
JDefinedClass dc = cm._class("foo.Bar");
JMethod m = dc.method(0, int.class, "foo");
m.body()._return(JExpr.lit(5));


File file = new File("./target/classes");
file.mkdirs();
cm.build(file);

我可以得到这个输出:

package foo;
public class Bar {
int foo() {
return  5;
}
}

使用 Eclipse JDT 的 AST 找到的解决方案
谢谢 贾尔斯

例如,使用以下代码:

AST ast = AST.newAST(AST.JLS3);
CompilationUnit cu = ast.newCompilationUnit();


PackageDeclaration p1 = ast.newPackageDeclaration();
p1.setName(ast.newSimpleName("foo"));
cu.setPackage(p1);


ImportDeclaration id = ast.newImportDeclaration();
id.setName(ast.newName(new String[] { "java", "util", "Set" }));
cu.imports().add(id);


TypeDeclaration td = ast.newTypeDeclaration();
td.setName(ast.newSimpleName("Foo"));
TypeParameter tp = ast.newTypeParameter();
tp.setName(ast.newSimpleName("X"));
td.typeParameters().add(tp);
cu.types().add(td);


MethodDeclaration md = ast.newMethodDeclaration();
td.bodyDeclarations().add(md);


Block block = ast.newBlock();
md.setBody(block);


MethodInvocation mi = ast.newMethodInvocation();
mi.setName(ast.newSimpleName("x"));


ExpressionStatement e = ast.newExpressionStatement(mi);
block.statements().add(e);


System.out.println(cu);

我可以得到这个输出:

package foo;
import java.util.Set;
class Foo<X> {
void MISSING(){
x();
}
}

也有 字符串模板。它是由 ANTLR 的作者,是相当强大的。

这真的取决于你想要做什么。代码生成本身就是一个主题。在没有特定用例的情况下,我建议查看流速代码生成/模板库。此外,如果您正在离线进行代码生成,我建议使用类似 ArgoUML 的工具从 UML 图/对象模型转换为 Java 代码。

我建立了一些东西,看起来非常像你的理论 DSL,所谓的“来源”,但在技术上,而不是一个直接项目的 ORM 我写。DSL 看起来像:

@Test
public void testTwoMethods() {
GClass gc = new GClass("foo.bar.Foo");


GMethod hello = gc.getMethod("hello");
hello.arguments("String foo");
hello.setBody("return 'Hi' + foo;");


GMethod goodbye = gc.getMethod("goodbye");
goodbye.arguments("String foo");
goodbye.setBody("return 'Bye' + foo;");


Assert.assertEquals(
Join.lines(new Object[] {
"package foo.bar;",
"",
"public class Foo {",
"",
"    public void hello(String foo) {",
"        return \"Hi\" + foo;",
"    }",
"",
"    public void goodbye(String foo) {",
"        return \"Bye\" + foo;",
"    }",
"",
"}",
"" }),
gc.toCode());
}

Https://github.com/stephenh/joist/blob/master/util/src/test/java/joist/sourcegen/gclasstest.java

它还可以做一些简单的事情,比如“自动组织导入”任何参数/返回类型的 FQCNs,自动删除这次代码运行中没有触及的任何旧文件,正确缩进内部类,等等。

其想法是,生成的代码应该看起来很漂亮,没有警告(未使用的导入等) ,就像您的其余代码一样。这么多生成的代码读起来很难看... 太可怕了。

无论如何,这里没有很多文档,但是我认为 API 非常简单/直观。如果有人感兴趣的话,Maven 的回购是 给你

例如: 1/

private JFieldVar generatedField;

2/

String className = "class name";
/* package name */
JPackage jp = jCodeModel._package("package name ");
/*  class name  */
JDefinedClass jclass = jp._class(className);
/* add comment */
JDocComment jDocComment = jclass.javadoc();
jDocComment.add("By AUTOMAT D.I.T tools : " + new Date() +" => " + className);
// génération des getter & setter & attribues


// create attribue
this.generatedField = jclass.field(JMod.PRIVATE, Integer.class)
, "attribue name ");
// getter
JMethod getter = jclass.method(JMod.PUBLIC, Integer.class)
, "attribue name ");
getter.body()._return(this.generatedField);
// setter
JMethod setter = jclass.method(JMod.PUBLIC, Integer.class)
,"attribue name ");
// create setter paramétre
JVar setParam = setter.param(getTypeDetailsForCodeModel(Integer.class,"param name");
// affectation  ( this.param = setParam )
setter.body().assign(JExpr._this().ref(this.generatedField), setParam);


jCodeModel.build(new File("path c://javaSrc//"));

有一个新的 写一次项目。基于模板的代码生成器。您使用 好极了编写自定义模板,并根据 Java 反射生成文件。这是生成任何文件的最简单方法。您可以通过生成 AspectJ 文件、基于 JPA 注释的 SQL、基于枚举的插入/更新等来创建 getters/settest/toString。

模板示例:

package ${cls.package.name};


public class ${cls.shortName}Builder {


public static ${cls.name}Builder builder() {
return new ${cls.name}Builder();
}
<% for(field in cls.fields) {%>
private ${field.type.name} ${field.name};
<% } %>
<% for(field in cls.fields) {%>
public ${cls.name}Builder ${field.name}(${field.type.name} ${field.name}) {
this.${field.name} = ${field.name};
return this;
}
<% } %>
public ${cls.name} build() {
final ${cls.name} data = new ${cls.name}();
<% for(field in cls.fields) {%>
data.${field.setter.name}(this.${field.name});
<% } %>
return data;
}
}

您可以使用 Roaster (https://github.com/forge/roaster)来进行代码生成。

这里有一个例子:

JavaClassSource source = Roaster.create(JavaClassSource.class);
source.setName("MyClass").setPublic();
source.addMethod().setName("testMethod").setPrivate().setBody("return null;")
.setReturnType(String.class).addAnnotation(MyAnnotation.class);
System.out.println(source);

将显示以下输出:

public class MyClass {
private String testMethod() {
return null;
}
}

下面是一个 JSON-to-POJO 项目,看起来很有趣:

Http://www.jsonschema2pojo.org/