深入Dagger:JavaPoet的使用
前言
最近在用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。这里介绍一下主要的方法。
- 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();
}
- 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();
}
- 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();
}
- 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的内容。
深入Dagger:JavaPoet的使用的更多相关文章
- 深入Dagger:自定义AutoValue
前言 上一篇文章介绍了JavaPoet的原理和使用,这里在介绍一下AutoValue的原理,并模仿自定义实现一个AutoValue. AutoValue的是Google为了实现ValueClass设计 ...
- [Android]使用Dagger 2来构建UserScope(翻译)
以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/6237731.html 使用Dagger 2来构建UserSco ...
- [Android]使用Dagger 2进行依赖注入 - Producers(翻译)
以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/6234811.html 使用Dagger 2进行依赖注入 - P ...
- [Android]在Dagger 2中使用RxJava来进行异步注入(翻译)
以下内容为原创,欢迎转载,转载请注明 来自天天博客: # 在Dagger 2中使用RxJava来进行异步注入 > 原文: 几星期前我写了一篇关于在Dagger 2中使用*Producers*进行 ...
- [Android]使用Dagger 2依赖注入 - DI介绍(翻译)
以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/5092083.html 使用Dagger 2依赖注入 - DI介 ...
- [Android]使用Dagger 2依赖注入 - API(翻译)
以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/5092525.html 使用Dagger 2依赖注入 - API ...
- [Android]使用Dagger 2依赖注入 - 自定义Scope(翻译)
以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/5095426.html 使用Dagger 2依赖注入 - 自定义 ...
- [Android]使用Dagger 2依赖注入 - 图表创建的性能(翻译)
以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/5098943.html 使用Dagger 2依赖注入 - 图表创 ...
- [Android]依赖注入框架google的dagger
分享一下Android依赖注入框架--Google升级版Dagger2框架 Google的Dagger2是对上一版squareup的Dagger改版,话不多说直接上项目代码. Dagger2源码 Da ...
随机推荐
- k8s进行与容器交互时报错:unable to upgrade connection: Unauthorized在k8s实现kubectl exec -it pod_ID sh出错解决
在创建pod时,进入pod失败 kubectl exec -it nginx-deployment-d55b94fd-xcrtg sh error检查问题,一直找不到答案,通过logs发现,同样不能实 ...
- bzoj2582 [Usaco2012Jan]Bovine Alliance
[Usaco2012Jan]Bovine Alliance Time Limit: 2 Sec Memory Limit: 128 MB Description Bessie and her bovi ...
- OAuth授权登录
一.写在前面 日常生活中,我们经常看到到一个网站时,需要登录的时候,都提供了第三方的登录,也就是说你可以使用你的微信,QQ,微博等账号进行授权登录.那么这个认证登录的东西到底是什么呢? 微信授权登录页 ...
- React-Native实战项目-导航器篇(一)
前言:官方文档已经看了一遍,但印象不是很深,于是在mooc上找了个实战学习项目做一做. 本篇目录: 基础导航练习√ 1.ReactNavigation之createStackNavigator导航器案 ...
- 选择器与过滤器(全)————JQ
JQ基础--选择器与过滤器(全) JQ选择器 <!DOCTYPE html> <html> <head> <meta charset="UTF-8& ...
- Js event对象offsetX,pageX,screenX,clientX详解
平时在测量元素位置时难以确定,下面给出具体的event对象中的各种属性,以便日后使用. 检测相对于浏览器的位置:clientX和clientY 当鼠标事件发生时,鼠标相对于浏览器左上 ...
- 【记录】git 拉取远程分支代码,同步到另一个git上
最近有需求从某git 上拉取所有分支代码同步到另一git上,现记录操作步骤,以便日后使用: 1:先克隆其中一个分支代码到本地环境 git clone -b test http://账号:密码@XXX. ...
- 七、Null、空以及0的区别
一.Null的区别 create database scort use scort create table emp ( empno int primary key, ename ), sal int ...
- js判断元素是否可见
dom元素是否可见可使用jq的is方法和dom的offsetParent === null方法 jq中 $(element).is(":visible") === true !!( ...
- JavaSE---用户交互---获取键盘输入
1.概述 1.1 JDK1.5提供了Scanner类,用来获取键盘输入: 1.2 Scanner类是 一个基于正则表达式的文本扫描器,可以从文件.输入流.字符串中解析出基本类型值.字符串值: 1. ...