Jdeparser学习笔记
Jdeparser简介
Jdeparser是JBOSS社区提供的Java源代码生成工具,可以方便生成Java源代码,常用于Annotation Processing中。
Jdeparser常用类
JDeparser
JDeparser类是JDeparser的入口,通过调用createSources函数创建JSources(源码容器)
JSources
JSources是源码容器,通过createSourceFile函数可以创建JSourceFile(源码文件)
JSourceFile
JSourceFile是源码文件,该类包含以下几个函数,用于创建源文件具体内容:
- _import 生成iimport语句
- importStatic 生成import语句(import类中的静态变量)
- blankLine 添加一个空行
- _class 生成class
- _enum 生成枚举类型
- _interface 生成接口
- annotationInterface 生成注解接口
_class, _enum, _interface, annotationInterface四个函数会返回JClassDef对象
JClassDef
JClassDef是类定义, 通过该类的一系列函数完成类具体内容定义:
- _extends 类继承哪个类
- _implements 类实现哪些接口
- erasedType 获取当前类擦除类型后的类型
- genericType 获取当前
- _enum 生成枚举值(该函数不会生成name, 可能是一个bug)
- typeParam 生成泛型信息
- method 生成方法
- annotate 生成类上的注解
- field 生成类属性
- constructor 生成构造函数
- staticInit 生成static静态代码块
- init 生成代码块(与staticInit不同, 每次new的时候都会执行init, 看看成构造函数的一部分)
Filer
文件编档员,用于存储JSources, 比如存储JSources到文件, 或者存储到ByteArrayOutputStream中
1 private final JFiler filer = new JFiler() { 2 public OutputStream openStream(final String packageName, final String fileName) throws IOException { 3 final Key key = new Key(packageName, fileName + ".java"); 4 if (!sourceFiles.containsKey(key)) { 5 final ByteArrayOutputStream stream = new ByteArrayOutputStream(); 6 if (sourceFiles.putIfAbsent(key, stream) == null) { 7 return stream; 8 } 9 } 10 throw new IOException("Already exists"); 11 } 12 };
FormatPreferences
生成源文件的格式配置, 比如空格个数等
组件示例
生成一个类
1JSources sources = JDeparser.createSources(getFiler(), new FormatPreferences()); 2JSourceFile bazFile = sources.createSourceFile("org.foo.bar", "Baz");
导入类
1#import java.math.BigDecimal; 2bazFile._import(BigDecimal.class);
生成类
1//@Controller 2//public class Baz<T extends String> extends XXClass implements XXInterface1, XXInterface2{} 3JClassDef classDef = bazFile._class(JMod.PUBLIC, "Baz"); 4classDef.typeParam("T")._extends(String.class); 5classDef._extends("XXClass"); 6classDef._implements("XXInterface1", "XXInterface2"); 7classDef.annotate("Controller");
生成函数声明
1//public String <T extends Thread> foo(T param1, String[] param2, Object... params) throws Exception {} 2public static final int VARARGS = 1 << 31; // JMod.VARARGS不是public的,不能访问 3JMethodDef methodDef = classDef.method(JMod.PUBLIC, String.class, "foo"); 4methodDef.typeParam("T")._extends(Thread.class); 5methodDef.param(JMod.FINAL, "T", "param1"); 6methodDef.param(0 , String[].class.getCanonicalName(), "param2"); 7methodDef.param(JMod.FINAL | VARARGS, Object.class, "params"); 8methodDef._throws(Exception.class);
生成属性
1// private static final String DEFAULT_VALUE = "ONE"; 2classDef.field(JMod.PRIVATE | JMod.STATIC | JMod.FINAL, String.class, "DEFAUL_VALUE", JExprs.str("ONE"));
生成函数体
1JBlock body = methodDef.body(); 2body.xxx
生成if语句
1/** 2if (var1 == null) { 3 var1 = "var1 value"; 4 if (var1.startWith("var1")) { 5 System.out.println(var1); 6 return; 7 } else if (var1.startWith("var1")) { 8 var1 = "var2 value"; 9 return; 10 } 11} 12**/ 13JIf if1 = body._if(JExprs.$v(var1).eq(JExpr.NULL)); 14if1.assign(JExprs.$v(var1), JExprs.str("var1 value")); 15 16JIf if1_1 = if1._if(JExprs.$v(var1).call("startWith").arg(JExprs.str("var1"))); 17if1_1.call(JTypes.$t(System.class).$v("out"), "println").arg(JExprs.$v(var1)); 18if1_1._return(); 19 20JIf if2 = if1.elseIf(JExprs.$v(var1).call("startWith").arg(JExprs.str("var1"))); 21 22JBlock block = if1._else();
注意: if1可以调用elseIf也可以调用_esle, 但是不能两者都调用, 只能调用其中一个, 否则会报错(这里是否有改进的空间)
生成for语句
1//foreach方式 for(String tmp : var1) var1需要可迭代 2body.forEach(0, String.class, "tmp", JExprs.$v(var1)); 3 4//for形式 for (int tmp = 0; tmp <= 10; tmp++) {} 5JFor for1 = body._for(); 6JVarDeclaration testVar = for1.init(0, int.class, "tmp", JExprs.decimal(0)); 7for1.test(JExprs.$v(testVar).le(JExprs.decimal(10))); 8for1.update(JExprs.$v(testVar).postInc());
生成while语句
1//java.sql.ResultSet resultSet = stmt.executeQuery("select * from xx"); 2//while (resultSet.next() == true) {} 3JCall queryCall = JExprs.$v("stmt").call("executeQuery").arg(JExprs.str("select * from xx")); 4JVarDeclaration resultSet = body.var(0, ResultSet.class, "resultSet", queryCall); 5JBlock whileBlock = body._while(JExprs.$v(resultSet).call("next").eq(JExpr.TRUE)); 6 7//do { 8// i++; 9//} while (i<10); 10JBlock doBlock = body._do(JExprs.$v("i<10")); 11doBlock.add(JExprs.$v("i").postInc());
方法调用
1//调用startWith函数, var1.startWith("var1") 2JExprs.$v(var1).call("startWith").arg(JExprs.str("var1"))
生成注释
1classDef.docComment().htmlTag("ul", true).attribute("class", "banana").htmlTag("li", false).text("A line item"); 2classDef.docComment().docTag("author", "Someone"); 3methodDef.blockComment().text("块注释"); 4var1.lineComment().text("行注释").nl();
较为完整的例子
代码如下;
1import org.jboss.jdeparser.*; 2import org.junit.Test; 3 4import java.io.BufferedReader; 5import java.io.ByteArrayInputStream; 6import java.io.IOException; 7import java.io.InputStreamReader; 8import java.math.BigDecimal; 9import java.sql.ResultSet; 10 11public class SimpleExampleTestCase extends AbstractGeneratingTestCase { 12 public static final int VARARGS = 1 << 31; 13 14 15 @Test 16 public void testSimple() throws IOException { 17 18 final JSources sources = JDeparser.createSources(getFiler(), new FormatPreferences()); 19 final JSourceFile bazFile = sources.createSourceFile("org.foo.bar", "Baz"); 20 21 bazFile._import(BigDecimal.class); 22 23 final JClassDef classDef = bazFile._class(JMod.PUBLIC, "Baz"); 24 classDef.docComment().htmlTag("ul", true).attribute("class", "banana").htmlTag("li", false).text("A line item"); 25 classDef.docComment().docTag("author", "Someone"); 26 27 classDef.typeParam("T")._extends(String.class); 28 classDef._extends("XXClass"); 29 classDef._implements("XXInterface1", "XXInterface2"); 30 classDef.annotate("Controller"); 31 32 JVarDeclaration var = classDef.field(JMod.PRIVATE | JMod.STATIC | JMod.FINAL, String.class, "DEFAUL_VALUE", JExprs.str("ONE")); 33 //var.add("ddd", JExpr.NULL); 34 35 JMethodDef methodDef = classDef.method(JMod.PUBLIC, String.class, "foo"); 36 methodDef.blockComment().text("块注释"); 37 ///methodDef.docComment().docTag("Date", "20190101"); 38 39 methodDef.typeParam("T")._extends(String.class); 40 methodDef.param(JMod.FINAL , "T", "param1"); 41 methodDef.param(0 , String[].class.getCanonicalName(), "param2"); 42 methodDef.param(JMod.FINAL | VARARGS, Object.class, "params"); 43 methodDef._throws(Exception.class); 44 45 JBlock body = methodDef.body(); 46 47 JVarDeclaration var1 = body.var(0, String.class, "var1", JExpr.NULL); 48 var1.lineComment().text("行注释").nl(); 49 JIf if1 = body._if(JExprs.$v(var1).eq(JExpr.NULL)); 50 if1.assign(JExprs.$v(var1), JExprs.str("var1 value")); 51 52 JIf if1_1 = if1._if(JExprs.$v(var1).call("startWith").arg(JExprs.str("var1"))); 53 if1_1.call(JTypes.$t(System.class).$v("out"), "println").arg(JExprs.$v(var1)); 54 if1_1._return(); 55 JIf if2 = if1.elseIf(JExprs.$v(var1).call("startWith").arg(JExprs.str("var1"))); 56 if2.assign(JExprs.$v(var1), JExprs.str("var2 value")); 57 if2._return(); 58// JBlock block = if1._else(); 59// block.assign(JExprs.$v(var1), JExprs.str("var3 value")); 60 61 62 body.forEach(0, String.class, "tmp", JExprs.$v(var1)); 63 JFor for1 = body._for(); 64 JVarDeclaration testVar = for1.init(0, int.class, "tmp", JExprs.decimal(0)); 65 for1.test(JExprs.$v(testVar).le(JExprs.decimal(10))); 66 for1.update(JExprs.$v(testVar).postInc()); 67 68 JCall queryCall = JExprs.$v("stmt").call("executeQuery").arg(JExprs.str("select * from xx")); 69 JVarDeclaration resultSet = body.var(0, ResultSet.class, "resultSet", queryCall); 70 JBlock whileBlock = body._while(JExprs.$v(resultSet).call("next").eq(JExpr.TRUE)); 71 72 73 JBlock doBlock = body._do(JExprs.$v("i<10")); 74 doBlock.add(JExprs.$v("i").postInc()); 75 76 sources.writeSources(); 77 final ByteArrayInputStream inputStream = openFile("org.foo.bar", "Baz.java"); 78 final BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); 79 String line; 80 while ((line = reader.readLine()) != null) { 81 System.out.println(line); 82 } 83 } 84} 85
输出结果如下;
1package org.foo.bar; 2 3import java.math.BigDecimal; 4 5/** 6 7 * <ul class="banana"> 8 * <li>A line item 9 * @author Someone 10 11 */ 12@Controller 13public class Baz<T extends String> extends XXClass implements XXInterface1, XXInterface2 { 14 private static final String DEFAUL_VALUE = "ONE"; 15 /* 16 * 块注释 17 */ 18 public <T extends String> String foo(final T param1, String[] param2, final Object... params) throws Exception { 19 // 行注释 20 String var1 = null; 21 if (var1 == null) { 22 var1 = "var1 value"; 23 if (var1.startWith("var1")) { 24 System.out.println(var1); 25 return; 26 } 27 } else if (var1.startWith("var1")) { 28 var1 = "var2 value"; 29 return; 30 } 31 for (String tmp : var1) {} 32 for (int tmp = 0; tmp <= 10; tmp++) {} 33 java.sql.ResultSet resultSet = stmt.executeQuery("select * from xx"); 34 while (resultSet.next() == true) {} 35 do { 36 i++; 37 } while (i<10); 38 } 39}