UDN-企业互联网技术人气社区

板块导航

浏览  : 1304
回复  : 0

[讨论交流] 深入Dagger:JavaPoet的使用

[复制链接]
呵呵燕的头像 楼主
发表于 2016-12-1 22:15:04 | 显示全部楼层 |阅读模式
  前言

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

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

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

  JavaPoet

  JavaPoet这样定义自己的项目。

 
  1.  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包。

  1.     <dependency>
  2.         <groupId>com.squareup</groupId>
  3.         <artifactId>javapoet</artifactId>
  4.         <version>1.7.0</version>
  5.     </dependency>
复制代码


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

  AnnotationSpec 添加MyAnnotation的注解,然后设置属性hello=world。

  1.   private static AnnotationSpec makeAnnotationSpec() {

  2.   AnnotationSpec.Builder builder = AnnotationSpec.builder(ClassName.get("org.wcong.test.poet", "MyAnnotation"));

  3.   CodeBlock.Builder codeBlockBuilder = CodeBlock.builder().add("$S", "world");

  4.   builder.addMember("hello", codeBlockBuilder.build());

  5.   return builder.build();

  6.   }
复制代码


  FieldSpec 创建hello的字段并初始化为“world”。

  1.   private static FieldSpec makeFieldSpec() {

  2.   FieldSpec.Builder fileSpecBuilder = FieldSpec.builder(String.class, "hello", Modifier.PRIVATE);

  3.   fileSpecBuilder.initializer(CodeBlock.of("\"world\""));

  4.   return fileSpecBuilder.build();

  5.   }
复制代码


  MethodSpec 创建getHello,setHello,toString方法。

  toString使用了ControlFlow判断了hello不等于null,返回"hello world",等于null的时候返回空。

  1.   private static MethodSpec makeToStringMethod() {

  2.   MethodSpec.Builder toStringBuilder = MethodSpec.methodBuilder("toString");

  3.   toStringBuilder.addModifiers(Modifier.PUBLIC);

  4.   toStringBuilder.returns(TypeName.get(String.class));

  5.   CodeBlock.Builder toStringCodeBuilder = CodeBlock.builder();

  6.   toStringCodeBuilder.beginControlFlow("if( hello != null )");

  7.   toStringCodeBuilder.add(CodeBlock.of("return \"hello \"+hello;\n"));

  8.   toStringCodeBuilder.nextControlFlow("else");

  9.   toStringCodeBuilder.add(CodeBlock.of("return \"\";\n"));

  10.   toStringCodeBuilder.endControlFlow();

  11.   toStringBuilder.addCode(toStringCodeBuilder.build());

  12.   return toStringBuilder.build();

  13.   }

  14.   private static MethodSpec makeSetMethod() {

  15.   MethodSpec.Builder setMethodSpecBuilder = MethodSpec.methodBuilder("setHello");

  16.   setMethodSpecBuilder.addModifiers(Modifier.PUBLIC);

  17.   setMethodSpecBuilder.returns(TypeName.VOID);

  18.   ParameterSpec.Builder parameterBuilder = ParameterSpec.builder(TypeName.get(String.class), "hello");

  19.   setMethodSpecBuilder.addParameter(parameterBuilder.build());

  20.   setMethodSpecBuilder.addCode(CodeBlock.builder().add("this.hello = hello;\n").build());

  21.   return setMethodSpecBuilder.build();

  22.   }

  23.   private static MethodSpec makeGetMethod() {

  24.   MethodSpec.Builder getMethodSpecBuilder = MethodSpec.methodBuilder("getHello");

  25.   getMethodSpecBuilder.addModifiers(Modifier.PUBLIC);

  26.   getMethodSpecBuilder.returns(TypeName.get(String.class));

  27.   getMethodSpecBuilder.addCode(CodeBlock.builder().add("return hello;\n").build());

  28.   return getMethodSpecBuilder.build();

  29.   }
复制代码


  JavaFile JavaPoet的主入口,用来描述Java源文件。

  1.   public static void main(String[] args) {

  2.   TypeSpec.Builder typeSpecBuilder = TypeSpec.classBuilder("JavaFile");

  3.   typeSpecBuilder.addAnnotation(makeAnnotationSpec());

  4.   typeSpecBuilder.addField(makeFieldSpec());

  5.   typeSpecBuilder.addMethods(makeMethodSpec());

  6.   JavaFile.Builder javaFileBuilder = JavaFile.builder("org.wcong.test.poet", typeSpecBuilder.build());

  7.   System.out.println(javaFileBuilder.build().toString());

  8.   }
复制代码


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

  1.   package org.wcong.test.poet;

  2.   import java.lang.String;

  3.   @MyAnnotation(

  4.   hello = "world"

  5.   )

  6.   class JavaFile {

  7.   private String hello = "world";

  8.   public String getHello() {

  9.   return hello;

  10.   }

  11.   public void setHello(String hello) {

  12.   this.hello = hello;

  13.   }

  14.   public String toString() {

  15.   if( hello != null ) {

  16.   return "hello "+hello;

  17.   } else {

  18.   return "";

  19.   }

  20.   }

  21.   }
复制代码


  结语

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

原文作者:wcong 来源:开发者头条
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关于我们
联系我们
  • 电话:010-86393388
  • 邮件:udn@yonyou.com
  • 地址:北京市海淀区北清路68号
移动客户端下载
关注我们
  • 微信公众号:yonyouudn
  • 扫描右侧二维码关注我们
  • 专注企业互联网的技术社区
版权所有:用友网络科技股份有限公司82041 京ICP备05007539号-11 京公网网备安1101080209224 Powered by Discuz!
快速回复 返回列表 返回顶部