前言

最近在用Dagger开发应用,Dagger是google在square的基础上去反射的依赖注入框架。

Dagger会根据定义的注解在编译阶段根据依赖注入的配置生成相应的代码,来减少运行期间反射的开销。

Dagger依赖了JavaPoet和JavaFormat来辅助实现生成代码,这里主要介绍下JavaPoet的内容和使用。

JavaPoet

JavaPoet这样定义自己的项目。

Use beautiful Java code to generate beautiful Java code

所以JavaPoet定义了一系列类来尽可能优雅的描述java源文件的结构。观察JavaPoet的代码主要的类可以分为以下几种:

  • Spec 用来描述Java中基本的元素,包括类型,注解,字段,方法和参数等。

    • AnnotationSpec
    • FieldSpec
    • MethodSpec
    • ParameterSpec
    • TypeSpec
  • Name 用来描述类型的引用,包括Void,原始类型(int,long等)和Java类等。
    • TypeName
    • ArrayTypeName
    • ClassName
    • ParameterizedTypeName
    • TypeVariableName
    • WildcardTypeName
  • CodeBlock 用来描述代码块的内容,包括普通的赋值,if判断,循环判断等。
  • JavaFile 完整的Java文件,JavaPoet的主要的入口。
  • CodeWriter 读取JavaFile并转换成可阅读可编译的Java源文件。

示例

下面通过一个例子来完整的实现一个Java类的定义。

通过下面的maven依赖可以引用JavaPoet包。

    <dependency>
<groupId>com.squareup</groupId>
<artifactId>javapoet</artifactId>
<version>1.7.0</version>
</dependency>

完整的代码放在Github。这里介绍一下主要的方法。

  1. AnnotationSpec 添加MyAnnotation的注解,然后设置属性hello=world
    private static AnnotationSpec makeAnnotationSpec() {
AnnotationSpec.Builder builder = AnnotationSpec.builder(ClassName.get("org.wcong.test.poet", "MyAnnotation"));
CodeBlock.Builder codeBlockBuilder = CodeBlock.builder().add("$S", "world");
builder.addMember("hello", codeBlockBuilder.build());
return builder.build();
}
  1. FieldSpec 创建hello的字段并初始化为“world”。
    private static FieldSpec makeFieldSpec() {
FieldSpec.Builder fileSpecBuilder = FieldSpec.builder(String.class, "hello", Modifier.PRIVATE);
fileSpecBuilder.initializer(CodeBlock.of("\"world\""));
return fileSpecBuilder.build();
}
  1. MethodSpec 创建getHello,setHello,toString方法。

    toString使用了ControlFlow判断了hello不等于null,返回"hello world",等于null的时候返回空。
    private static MethodSpec makeToStringMethod() {
MethodSpec.Builder toStringBuilder = MethodSpec.methodBuilder("toString");
toStringBuilder.addModifiers(Modifier.PUBLIC);
toStringBuilder.returns(TypeName.get(String.class));
CodeBlock.Builder toStringCodeBuilder = CodeBlock.builder();
toStringCodeBuilder.beginControlFlow("if( hello != null )");
toStringCodeBuilder.add(CodeBlock.of("return \"hello \"+hello;\n"));
toStringCodeBuilder.nextControlFlow("else");
toStringCodeBuilder.add(CodeBlock.of("return \"\";\n"));
toStringCodeBuilder.endControlFlow();
toStringBuilder.addCode(toStringCodeBuilder.build());
return toStringBuilder.build();
}
private static MethodSpec makeSetMethod() {
MethodSpec.Builder setMethodSpecBuilder = MethodSpec.methodBuilder("setHello");
setMethodSpecBuilder.addModifiers(Modifier.PUBLIC);
setMethodSpecBuilder.returns(TypeName.VOID);
ParameterSpec.Builder parameterBuilder = ParameterSpec.builder(TypeName.get(String.class), "hello");
setMethodSpecBuilder.addParameter(parameterBuilder.build());
setMethodSpecBuilder.addCode(CodeBlock.builder().add("this.hello = hello;\n").build());
return setMethodSpecBuilder.build();
}
private static MethodSpec makeGetMethod() {
MethodSpec.Builder getMethodSpecBuilder = MethodSpec.methodBuilder("getHello");
getMethodSpecBuilder.addModifiers(Modifier.PUBLIC);
getMethodSpecBuilder.returns(TypeName.get(String.class));
getMethodSpecBuilder.addCode(CodeBlock.builder().add("return hello;\n").build());
return getMethodSpecBuilder.build();
}
  1. JavaFile JavaPoet的主入口,用来描述Java源文件。
    public static void main(String[] args) {
TypeSpec.Builder typeSpecBuilder = TypeSpec.classBuilder("JavaFile");
typeSpecBuilder.addAnnotation(makeAnnotationSpec());
typeSpecBuilder.addField(makeFieldSpec());
typeSpecBuilder.addMethods(makeMethodSpec());
JavaFile.Builder javaFileBuilder = JavaFile.builder("org.wcong.test.poet", typeSpecBuilder.build());
System.out.println(javaFileBuilder.build().toString());
}

运行后输出下面的信息,就是一个完整的类文件了

package org.wcong.test.poet;

import java.lang.String;

@MyAnnotation(
hello = "world"
)
class JavaFile {
private String hello = "world"; public String getHello() {
return hello;
} public void setHello(String hello) {
this.hello = hello;
} public String toString() {
if( hello != null ) {
return "hello "+hello;
} else {
return "";
}
}
}

结语

dagger使用JavaPoet来保存自动生成的类的信息,并通过JavaFormat来格式化生成的Java源文件。后面会介绍关于JavaFormat的内容。

最新文章

  1. Java集合系列:-----------04fail-fast总结(通过ArrayList来说明fail-fast的原理以及解决办法)
  2. 在linux安装mysql,并设置远程访问
  3. osgi 命令
  4. WIN 8.1使用常见问题及解决
  5. 升级ionic版本后,创建新项目报Error Initializing app错误解决
  6. POJ 2352 Stars
  7. tinyxml_settattr
  8. RAC分解步骤之一,在oracle linux 4u4上安装oracle 10.2.0.1.0操作日志
  9. [Design Pattern] Front Controller Pattern 简单案例
  10. windows中如何查看某个端口被谁占用
  11. JavaScript中值类型和引用类型的区别
  12. Android开发之AsyncTask示例Demo
  13. MySql5.7环境搭建
  14. ATM+购物商城完整版
  15. (27)How to stay calm when you know you&#39;ll be stressed
  16. Netcat实用操作
  17. Mysql查看表的建表语句
  18. 线程池 多线程运行结束后 如何关闭? ExecutorService的正确关闭方法
  19. java使用wait(),notify(),notifyAll()实现等待/通知机制
  20. 第三百五十七节,Python分布式爬虫打造搜索引擎Scrapy精讲—利用开源的scrapy-redis编写分布式爬虫代码

热门文章

  1. 容器下载的是centos8的镜像,scp出现packet_write_wait: Connection to **** port 22: Broken pipe 问题解决
  2. Python3学习笔记——异常处理
  3. 以python为例讲解闭包机制
  4. SpringMvc获取前端的数据@RequestBody请求体/@PathVaribale/@RequestParam【支持Ajax】
  5. python3.x 浅谈修饰器
  6. [BOOKS]Big Data: Principles and best practices of scalable realtime data systems
  7. Scrapy爬虫框架的使用
  8. Vue学习笔记【32】——Vue路由(watch、computed和methods之间的对比)
  9. Python之-在字典、列表、集合中刷选数据
  10. vue之slot用法