Javapoet:是生成.java源文件的开源API

以生成一个HelloWrold.java文件为例:

 package com.example.helloworld;

 public final class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, JavaPoet!");
}
}
 MethodSpec main = MethodSpec.methodBuilder("main")
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
.returns(void.class)
.addParameter(String[].class, "args")
.addStatement("$T.out.println($S)", System.class, "Hello, JavaPoet!")
.build(); TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld")
.addModifiers(Modifier.PUBLIC, Modifier.FINAL)
.addMethod(main)
.build(); JavaFile javaFile = JavaFile.builder("com.example.helloworld", helloWorld)
.build(); ///javaFile.writeTo(System.out); //System.out print to the console
//generate a java file in user.dir
String directory = System.getProperty("user.dir");
File file = new File(directory + SEPARATOR + "HelloWrold.java");
PrintStream ps = new PrintStream(new FileOutputStream(file));
javaFile.writeTo(ps);
ps.flush();
ps.close();

在这个例子中用到了三个类的对象 :JavaFile  MethodSpec   TypeSpec,首先来看第一个JavaFile

  public static Builder builder(String packageName, TypeSpec typeSpec) {
checkNotNull(packageName, "packageName == null");
checkNotNull(typeSpec, "typeSpec == null");
return new Builder(packageName, typeSpec);
}

Builder是JavaFile中的一个静态内部类,由此可以看到 Javapoet使用的是建造者设计模式。通过packageName 和TypeSpec生成一个Builder对象,然后调用Builder类的build方法:

 public JavaFile build() {
return new JavaFile(this);
}

返回当前的JavaFile对象,然后调用writeto方法将该对象写入流/文件。

接下来看看构造Builder方法时使用的TypeSpec是什么。

staticBlock:A generated class, interface, or enum declaration:对于要生成的类,接口或枚举的声明。就是定义 类 接口或者枚举,定义的时候需要给他们命名,添加权限修饰符 是否静态 是否抽象 是否final,添加方法等操作

所以这个类里面有静态方法classBuilder interfaceBuilder enumBuilder 以及匿名内部类anonymousClassBuilder,这些静态方法都返回对应的一个Builder对象

该Builder对象是TypeSpec中的静态内部类,用于构建当前的TypeSpec对象。在内部类Builder中应该有添加权限修饰符/注释/注解/变量等操作来构建一个类或者接口枚举

MethodSpec:A generated constructor or method declaration. 对方法的声明,包括构造方法。所以这个类里面有methodBuilder constructorBuilder,返回该类的一个Builder对象,这个builder也是该类的一个静态内部类。并且这个Builder内部类中同样包括添加权限修饰符/注释/注解等方法,另外方法有返回值,参数 Comment 语句来构建一个方法

同样的原理,FieldSpec是对成员变量的声明,而且里面也有一个可以返回当前对象的builder静态内部类,在这个builder中同样有添加注释注解访问修饰符等的操作,来构建一个变量。

类变量等已经定义完毕,接下来我们分析一下是如何生成java文件的,回到JavaFile的writeTo方法

这里有很多重载的writeTo方法,最终都会调用

  public void writeTo(Appendable out) throws IOException {
// First pass: emit the entire class, just to collect the types we'll need to import.
CodeWriter importsCollector = new CodeWriter(NULL_APPENDABLE, indent, staticImports);
emit(importsCollector);
Map<String, ClassName> suggestedImports = importsCollector.suggestedImports(); // Second pass: write the code, taking advantage of the imports.
CodeWriter codeWriter = new CodeWriter(out, indent, suggestedImports, staticImports);
emit(codeWriter);
}
CodeWriter是什么呢?CodeWriter将JavaFile转换为适用于人类和javac使用的字符串,实现了导入,缩进和延期变量名称。

以FieldSpec为例来说明CodeWriter的用法:

 void emit(CodeWriter codeWriter, Set<Modifier> implicitModifiers) throws IOException {
codeWriter.emitJavadoc(javadoc);
codeWriter.emitAnnotations(annotations, false);
codeWriter.emitModifiers(modifiers, implicitModifiers);
codeWriter.emit("$T $L", type, name);
if (!initializer.isEmpty()) {
codeWriter.emit(" = ");
codeWriter.emit(initializer);
}
codeWriter.emit(";\n");
}

这段代码是在生成变量时调用的。第二行是写javadoc注释,第三行是写注解,第四行是写访问修饰符,第五行是写该变量的类型和变量名,第6-9行是判断变量是否有初始化值,如果有就写初始化值

第10行;代表该变量写出完毕。至此,HelloWorld.java的生成过程分析完毕。

用到的一些集合类中的方法:

Collections.singletonList

Collections.emptyList()

EnumSet.copyOf(Set<Modifier> modifiers)

Collections.unmodifiableList(new ArrayList<>(collection));   返回指定列表的不可修改视图。 此方法允许模块为用户提供对内部列表的“只读”访问权限。

Javapoet源码解析的更多相关文章

  1. 阿里ARouter使用及源码解析(一)

    在app的开发中,页面之间的相互跳转是最基本常用的功能.在Android中的跳转一般通过显式intent和隐式intent两种方式实现的,而Android的原生跳转方式会存在一些缺点: 显式inten ...

  2. 【原】Android热更新开源项目Tinker源码解析系列之三:so热更新

    本系列将从以下三个方面对Tinker进行源码解析: Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Android热更新开源项目Tinker源码解析系列之二:资源文件热更新 A ...

  3. 【原】Android热更新开源项目Tinker源码解析系列之一:Dex热更新

    [原]Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Tinker是微信的第一个开源项目,主要用于安卓应用bug的热修复和功能的迭代. Tinker github地址:http ...

  4. 【原】Android热更新开源项目Tinker源码解析系列之二:资源文件热更新

    上一篇文章介绍了Dex文件的热更新流程,本文将会分析Tinker中对资源文件的热更新流程. 同Dex,资源文件的热更新同样包括三个部分:资源补丁生成,资源补丁合成及资源补丁加载. 本系列将从以下三个方 ...

  5. 多线程爬坑之路-Thread和Runable源码解析之基本方法的运用实例

    前面的文章:多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类) 多线程爬坑之路-Thread和Runable源码解析 前面 ...

  6. jQuery2.x源码解析(缓存篇)

    jQuery2.x源码解析(构建篇) jQuery2.x源码解析(设计篇) jQuery2.x源码解析(回调篇) jQuery2.x源码解析(缓存篇) 缓存是jQuery中的又一核心设计,jQuery ...

  7. Spring IoC源码解析——Bean的创建和初始化

    Spring介绍 Spring(http://spring.io/)是一个轻量级的Java 开发框架,同时也是轻量级的IoC和AOP的容器框架,主要是针对JavaBean的生命周期进行管理的轻量级容器 ...

  8. jQuery2.x源码解析(构建篇)

    jQuery2.x源码解析(构建篇) jQuery2.x源码解析(设计篇) jQuery2.x源码解析(回调篇) jQuery2.x源码解析(缓存篇) 笔者阅读了园友艾伦 Aaron的系列博客< ...

  9. jQuery2.x源码解析(设计篇)

    jQuery2.x源码解析(构建篇) jQuery2.x源码解析(设计篇) jQuery2.x源码解析(回调篇) jQuery2.x源码解析(缓存篇) 这一篇笔者主要以设计的角度探索jQuery的源代 ...

随机推荐

  1. STL源码标注_空间适配器

    /* stl_alloc.h */ SGI STL空间适配器的主要由alloc.h和stl_alloc.h实现 SGI STL空间适配器的核心: 第一级适配器__malloc_alloc_templa ...

  2. Ocelot中文文档-授权

    Ocelot支持基于声明的授权. 这意味着如果您有要授权的路由,您可以将以下内容添加到您的ReRoute配置中. "RouteClaimsRequirement": { " ...

  3. python中元组、列表、字典、集合知识

    像列表一样处理字符串: 仅需要看字符串的首字符就知道如何处理该字符串的情况也很常见.例如,如果有一个姓与名的列表,您可以使用与列表相同的语法查看名与姓的第一个字符.这种看待字符串的方法叫做分片(sli ...

  4. eclipse中maven下载不了私服上面的第三方包问题

    问题描述在nexus中上传了第三方jar包,在本地项目中添加了引用,但就是下载不下来. 转载文章 1. 打开windows -> preferences -> maven,勾选如图所示 2 ...

  5. .NET开发设计模式-获取某个接口下面所有的派生类

    using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using Sy ...

  6. Maven学习(一)-- Maven入门

    摘自:http://www.cnblogs.com/xdp-gacl/p/3498271.html 一.Maven的基本概念 Maven(翻译为"专家","内行" ...

  7. 第四章——训练模型(Training Models)

    前几章在不知道原理的情况下,已经学会使用了多个机器学习模型机器算法.Scikit-Learn很方便,以至于隐藏了太多的实现细节. 知其然知其所以然是必要的,这有利于快速选择合适的模型.正确的训练算法. ...

  8. 《Spring Cloud与Docker微服务架构实战》配套代码

    不才写了本使用Spring Cloud玩转微服务架构的书,书名是<Spring Cloud与Docker微服务架构实战> - 周立,已于2017-01-12交稿.不少朋友想先看看源码,现将 ...

  9. 关于JSON字符串的处理与总结 【原创】

    这两天帮另一个实习生处理点前端的问题 遇到点JSON的处理 总结如下 ①一个JSON字符串    JSON.Parse(JSON字符串)—>JSON对象Object ②一个JSONArray   ...

  10. jQuery学习之旅 Item10 ajax快餐

    1. 摘要 本系列文章将带您进入jQuery的精彩世界, 其中有很多作者具体的使用经验和解决方案, 即使你会使用jQuery也能在阅读中发现些许秘籍. 本篇文章讲解如何使用jQuery方便快捷的实现A ...