Jdeparser学习笔记

Jdeparser学习笔记

Jdeparser简介

Jdeparser是JBOSS社区提供的Java源代码生成工具,可以方便生成Java源代码,常用于Annotation Processing中。

Jdeparser常用类

JDeparser

JDeparser类是JDeparser的入口,通过调用createSources函数创建JSources(源码容器)

JSources

JSources是源码容器,通过createSourceFile函数可以创建JSourceFile(源码文件)

JSourceFile

JSourceFile是源码文件,该类包含以下几个函数,用于创建源文件具体内容:

  1. _import 生成iimport语句
  2. importStatic 生成import语句(import类中的静态变量)
  3. blankLine 添加一个空行
  4. _class 生成class
  5. _enum 生成枚举类型
  6. _interface 生成接口
  7. annotationInterface 生成注解接口

_class, _enum, _interface, annotationInterface四个函数会返回JClassDef对象

JClassDef

JClassDef是类定义, 通过该类的一系列函数完成类具体内容定义:

  1. _extends 类继承哪个类
  2. _implements 类实现哪些接口
  3. erasedType 获取当前类擦除类型后的类型
  4. genericType 获取当前
  5. _enum 生成枚举值(该函数不会生成name, 可能是一个bug)
  6. typeParam 生成泛型信息
  7. method 生成方法
  8. annotate 生成类上的注解
  9. field 生成类属性
  10. constructor 生成构造函数
  11. staticInit 生成static静态代码块
  12. init 生成代码块(与staticInit不同, 每次new的时候都会执行init, 看看成构造函数的一部分)
Filer

文件编档员,用于存储JSources, 比如存储JSources到文件, 或者存储到ByteArrayOutputStream中

    private final JFiler filer = new JFiler() {
        public OutputStream openStream(final String packageName, final String fileName) throws IOException {
            final Key key = new Key(packageName, fileName + ".java");
            if (!sourceFiles.containsKey(key)) {
                final ByteArrayOutputStream stream = new ByteArrayOutputStream();
                if (sourceFiles.putIfAbsent(key, stream) == null) {
                    return stream;
                }
            }
            throw new IOException("Already exists");
        }
    };
FormatPreferences

生成源文件的格式配置, 比如空格个数等

组件示例

生成一个类
JSources sources = JDeparser.createSources(getFiler(), new FormatPreferences());
JSourceFile bazFile = sources.createSourceFile("org.foo.bar", "Baz");
导入类
#import java.math.BigDecimal;
bazFile._import(BigDecimal.class);
生成类
//@Controller
//public class Baz<T extends String> extends XXClass implements XXInterface1, XXInterface2{}
JClassDef classDef = bazFile._class(JMod.PUBLIC, "Baz");
classDef.typeParam("T")._extends(String.class);
classDef._extends("XXClass");
classDef._implements("XXInterface1", "XXInterface2");
classDef.annotate("Controller");
生成函数声明
//public String <T extends Thread> foo(T param1, String[] param2, Object... params) throws Exception {}
public static final int VARARGS = 1 << 31; // JMod.VARARGS不是public的,不能访问
JMethodDef methodDef = classDef.method(JMod.PUBLIC, String.class, "foo");
methodDef.typeParam("T")._extends(Thread.class);
methodDef.param(JMod.FINAL, "T", "param1");
methodDef.param(0 , String[].class.getCanonicalName(), "param2");
methodDef.param(JMod.FINAL | VARARGS, Object.class, "params");
methodDef._throws(Exception.class);
生成属性
// private static final String DEFAULT_VALUE = "ONE";
classDef.field(JMod.PRIVATE | JMod.STATIC | JMod.FINAL, String.class, "DEFAUL_VALUE", JExprs.str("ONE"));
生成函数体
JBlock body = methodDef.body();
body.xxx
生成if语句
/**
if (var1 == null) {
    var1 = "var1 value";
    if (var1.startWith("var1")) {
        System.out.println(var1);
        return;
    } else if (var1.startWith("var1")) {
        var1 = "var2 value";
        return;
    }
}
**/
JIf if1 = body._if(JExprs.$v(var1).eq(JExpr.NULL));
if1.assign(JExprs.$v(var1), JExprs.str("var1 value"));

JIf if1_1 = if1._if(JExprs.$v(var1).call("startWith").arg(JExprs.str("var1")));
if1_1.call(JTypes.$t(System.class).$v("out"), "println").arg(JExprs.$v(var1));
if1_1._return();

JIf if2 = if1.elseIf(JExprs.$v(var1).call("startWith").arg(JExprs.str("var1")));

JBlock block = if1._else();

注意: if1可以调用elseIf也可以调用_esle, 但是不能两者都调用, 只能调用其中一个, 否则会报错(这里是否有改进的空间)

生成for语句
//foreach方式 for(String tmp : var1)  var1需要可迭代
body.forEach(0, String.class, "tmp", JExprs.$v(var1));

//for形式 for (int tmp = 0; tmp <= 10; tmp++) {}
JFor for1 = body._for();
JVarDeclaration testVar = for1.init(0, int.class, "tmp", JExprs.decimal(0));
for1.test(JExprs.$v(testVar).le(JExprs.decimal(10)));
for1.update(JExprs.$v(testVar).postInc());
生成while语句
//java.sql.ResultSet resultSet = stmt.executeQuery("select * from xx");
//while (resultSet.next() == true) {}
JCall queryCall = JExprs.$v("stmt").call("executeQuery").arg(JExprs.str("select * from xx"));
JVarDeclaration resultSet = body.var(0, ResultSet.class, "resultSet", queryCall);
JBlock whileBlock = body._while(JExprs.$v(resultSet).call("next").eq(JExpr.TRUE));

//do {
//    i++;
//} while (i<10);
JBlock doBlock = body._do(JExprs.$v("i<10"));
doBlock.add(JExprs.$v("i").postInc());
方法调用
//调用startWith函数, var1.startWith("var1")
JExprs.$v(var1).call("startWith").arg(JExprs.str("var1"))
生成注释
classDef.docComment().htmlTag("ul", true).attribute("class", "banana").htmlTag("li", false).text("A line item");
classDef.docComment().docTag("author", "Someone");
methodDef.blockComment().text("块注释");
var1.lineComment().text("行注释").nl();

较为完整的例子

代码如下;

import org.jboss.jdeparser.*;
import org.junit.Test;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.sql.ResultSet;

public class SimpleExampleTestCase extends AbstractGeneratingTestCase {
    public static final int VARARGS            = 1 << 31;


    @Test
    public void testSimple() throws IOException {

        final JSources sources = JDeparser.createSources(getFiler(), new FormatPreferences());
        final JSourceFile bazFile = sources.createSourceFile("org.foo.bar", "Baz");

        bazFile._import(BigDecimal.class);

        final JClassDef classDef = bazFile._class(JMod.PUBLIC, "Baz");
        classDef.docComment().htmlTag("ul", true).attribute("class", "banana").htmlTag("li", false).text("A line item");
        classDef.docComment().docTag("author", "Someone");

        classDef.typeParam("T")._extends(String.class);
        classDef._extends("XXClass");
        classDef._implements("XXInterface1", "XXInterface2");
        classDef.annotate("Controller");

       JVarDeclaration var = classDef.field(JMod.PRIVATE | JMod.STATIC | JMod.FINAL, String.class, "DEFAUL_VALUE", JExprs.str("ONE"));
        //var.add("ddd", JExpr.NULL);

        JMethodDef methodDef = classDef.method(JMod.PUBLIC, String.class, "foo");
        methodDef.blockComment().text("块注释");
        ///methodDef.docComment().docTag("Date", "20190101");

        methodDef.typeParam("T")._extends(String.class);
        methodDef.param(JMod.FINAL , "T", "param1");
        methodDef.param(0 , String[].class.getCanonicalName(), "param2");
        methodDef.param(JMod.FINAL | VARARGS, Object.class, "params");
        methodDef._throws(Exception.class);

        JBlock body = methodDef.body();

        JVarDeclaration var1 = body.var(0, String.class, "var1", JExpr.NULL);
        var1.lineComment().text("行注释").nl();
        JIf if1 = body._if(JExprs.$v(var1).eq(JExpr.NULL));
        if1.assign(JExprs.$v(var1), JExprs.str("var1 value"));

        JIf if1_1 = if1._if(JExprs.$v(var1).call("startWith").arg(JExprs.str("var1")));
        if1_1.call(JTypes.$t(System.class).$v("out"), "println").arg(JExprs.$v(var1));
        if1_1._return();
        JIf if2 = if1.elseIf(JExprs.$v(var1).call("startWith").arg(JExprs.str("var1")));
        if2.assign(JExprs.$v(var1), JExprs.str("var2 value"));
        if2._return();
//        JBlock block = if1._else();
//        block.assign(JExprs.$v(var1), JExprs.str("var3 value"));


        body.forEach(0, String.class, "tmp", JExprs.$v(var1));
        JFor for1 = body._for();
        JVarDeclaration testVar = for1.init(0, int.class, "tmp", JExprs.decimal(0));
        for1.test(JExprs.$v(testVar).le(JExprs.decimal(10)));
        for1.update(JExprs.$v(testVar).postInc());

        JCall queryCall = JExprs.$v("stmt").call("executeQuery").arg(JExprs.str("select * from xx"));
        JVarDeclaration resultSet = body.var(0, ResultSet.class, "resultSet", queryCall);
        JBlock whileBlock = body._while(JExprs.$v(resultSet).call("next").eq(JExpr.TRUE));


       JBlock doBlock = body._do(JExprs.$v("i<10"));
       doBlock.add(JExprs.$v("i").postInc());
       
        sources.writeSources();
        final ByteArrayInputStream inputStream = openFile("org.foo.bar", "Baz.java");
        final BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
        String line;
        while ((line = reader.readLine()) != null) {
            System.out.println(line);
        }
    }
}

输出结果如下;

package org.foo.bar;

import java.math.BigDecimal;

/**

 * <ul class="banana">
 *   <li>A line item
 * @author Someone

 */
@Controller
public class Baz<T extends String> extends XXClass implements XXInterface1, XXInterface2 {
    private static final String DEFAUL_VALUE = "ONE";
    /*
     * 块注释
     */
    public <T extends String> String foo(final T param1, String[] param2, final Object... params) throws Exception {
        // 行注释
        String var1 = null;
        if (var1 == null) {
            var1 = "var1 value";
            if (var1.startWith("var1")) {
                System.out.println(var1);
                return;
            }
        } else if (var1.startWith("var1")) {
            var1 = "var2 value";
            return;
        }
        for (String tmp : var1) {}
        for (int tmp = 0; tmp <= 10; tmp++) {}
        java.sql.ResultSet resultSet = stmt.executeQuery("select * from xx");
        while (resultSet.next() == true) {}
        do {
            i++;
        } while (i<10);
    }
}

转载于:https://my.oschina.net/u/2328171/blog/3065322

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值