GreenDAO系列(二) GreenDao 代码生成策略分析

简介

本篇文章主要介绍GreenDao的代码生成策略的实现方式,以及介绍Android中常用开源框架的代码生成策略,通过对GreenDao代码生成方法的研究和学习,提升自我编程能力,尝试编写代码生成框架的目的。
本文是介绍GreenDao系列文章的第二篇,前面一篇是对GreenDao框架的介绍,以及GreenDao的使用。后面还会有一篇是对GreenDao与数据库打交道相关的讲解。

目录

  • 1.GreenDao结构
  • 2.GreenDao顶级视图
  • 3.GreenDao代码生成流程图
  • 4.Gradle 插件相关
  • 5.Android注解相关
  • 6.代码生成框架FreeMarker
  • 7.相关参考

1.GreenDao结构

GreenDao相关包介绍

GreenDao框架中组件共有6个,这其中不仅包含咱们引入的工程中的代码也包含GreenDao使用gradle的插件执行代码,代码对比工具、注解生成对象的相关。
Android中使用比较常见的注解处理器是APT,但是GreenDao使用的是JDT。
GreenDao官方提供的是代码开源,但是在GreenDao的GitHub只提供了greendao、greendao-api、greendao-generator这三个模块,另外三个模块在Gradle的cache文件夹中也是找不到源码的,要想学习这部分源码只能反编译和分析来解决。

2.GreenDao顶级视图

GreenDao顶级视图

上图对照着GreenDao的整体架构进行分析,绘制出来的GreenDao整体结构图。包含GreenDao的各个组件以及开发者使用GreenDao中的注解编写代码,注解生成的代码和GreenDao的配合完成程序与数据库打交道的工作。

先从左上角的模块开始,original-model是android开发者使用GreenDao的注解编写代码,编写出最原始的model类,添加上GreenDao的注解。这时候GreenDao的使用者就初步完成了工作。
再看左上角的greendao-api 注解即标准,所谓的GreenDao注解就是在这里定义的,开发者依据greendao-api中的注解添加到的model中,GreenDao代码生成相关模块也是依据greendao-api中的注解来生成对应的dao代码。到此GreenDao的代码编写和生成代码逻辑似乎有一些眉目了。
再来看结构图的右上这部分模块,greendao-gradle-plugin模块是Gradle的插件。就是android在编译时使用的编译工具Gradle,别和GreenDao弄混了。使用Gradle插件的目的是每次在编译的时候,就会有相关执行代码的入口,GreenDao就可以在这个时机来生成代码。提醒开发者注意的是Gradle的插件是在编译期执行的,就意味着不会影响app代码在用户手机的运行效率,但是会影响apk的编译速度。在选择使用GreenDao的时候也要考虑这方面的因素。
使用GreenDao除了官方样例那样全部引入以外,还有另外一种方案,就是用Demo工程去生成代码,再将生成出来的代码copy到主工程中使用,主工程只依赖greendao-core和greendao-api,GreenDao的Gradle插件在主工程并不使用,在Demo工程执行插件生成代码的工作。此方法提供给大家参考和选择。
greendao-code-modifier是代码自动生成模块的中间控制者,比对代码中的注解是否需要重新生成,调用greenrobot-jdt收集代码中的注解信息。
greendao-code-modifier模块调用greendao-generator来生成对应的代码,greendao使用的代码生成模板为freemarker开源框架。
结构图的下半部分是与数据库打交道的部分,也就是实际代码运行的部分,最上面的是生成的代码DaoMaster、DaoSession、Dao,一般会生成这三个类,在一定条件下还会生成entity和content-provider、dao-unit-test相关的代码。
下半部分的中间是greendao-core模块,就是生成的代码与greendao-core代码配合实现与最底下的SQLlite通讯完成数据库相关的操作。

3.GreenDao代码生成流程图

GreenDao流程图

以上是GreenDao相关的代码生成的实现,下面是相关技术点的介绍,如果有对下面的技术点了解的可以跳过其中的章节。

4.Gradle 插件相关

如何开发一个gradle plugin,网上例子很多,这里简单列举自定义Gradle plugin插件的步骤

  • 1.新建module,删除module中大部分内容。
  • 2.新建MyPlugin.groovy,实现org.gradle.api.Plugin接口,apply入口方法。
  • 3.建立resources目录、创建.properties文件.
  • 4.配置gradle文件、上传maven库。
  • 5执行插件。

注意:这里properties的名字及里边的配置,以及Gradle文件中的配置只有实践尝试了之后才能搞明白都是做什么用的。在本篇文章的最后面有参考自定义Gradle的插件的链接,可以学习一下。
GreenDao的Gradle插件的代码是
greendao-gradle-plugin-3.2.2.jar --> Greendao3GradlePlugin

5.Android注解相关

这部分是对注解和注解处理器做简单的介绍,有了这些基础才能对GreenDao中注解相关知识分析明白,以及研究明白这些代码是怎么串联起来的和这些代码是做什么用的。如果对注解和注解处理器已经熟悉了可以直接跳过这部分介绍。

Annotation(注解)是JDK5.0及以后版本引入的。它可以用于创建文档,跟踪代码中的依赖性,甚至执行基本编译时检查。从某些方面看,annotation就像修饰符一样被使用,并应用于包、类 型、构造方法、方法、成员变量、参数、本地变量的声明中。这些信息被存储在Annotation的“name=value”结构对中。

功能作用:
1.编写文档:通过代码里标识的元数据生成文档
2.代码分析:通过代码里标识的元数据对代码进行分析
3.编译检查:通过代码里标识的元数据让编译器能实现基本的编译检查

根据注解使用的方法和用途分类:
1.JDK内置系统注解
2.元注解
3.自定义注解

元注解
1.@Target 描述注解修饰的范围, 类、接口、包、方法等类型。
2.@Retention 注解被保留的时间长短
3.@Document javadoc
4.@Inhrited 注解类的继承关系
(注:元注解的作用就是负责注解其他注解 java 5.0定义了4个)

RetentionPoicy取值
1.SOURCE:在源文件中有效(即源文件保留)
2.CLASS:在class文件中有效(即class保留)
3.RUNTIME:在运行时有效(即运行时保留)

GreenDao中的注解是在greendao-api-3.2.2.jar 包中定义的、全部为source级别。

开发中常见的注解处理器有反射、APT、JDT等。
反射在java开发中是比较常见的、apt是android开发经常使用的方式、jdt是eclipse开发工具使用的处理器。这个在国内用的比较少。JDT的介绍是我从eclipse官网找到的,在文章最后有相关的链接。
JDT为Eclipse中的Java 5项目添加了注释处理支持,它提供了以下功能:
支持为Sun的命令行apt工具编写的运行注释处理器。
增量构建期间基于注释的构建构件的贡献。
基于注释的问题的问题标记的贡献。

GreenDao使用的注解处理器是JDT。

6.代码生成框架FreeMarker

FreeMarker不是什么新技术,在java服务端的开发中已经使用好多年,基本原理就是写一个模板,然后在模板里加入判断和变量,支持一些基本的声明、变量、判断、循环等语法。将实体类已对象的形式作为参数传递到模板中,最后将对象的值和模板进行结合生成对应的代码。做android的同学可以用DataBinding、MVVM来做比较学习,原理相似。FreeMarker还是比较容易学习,在本篇文章的最后有FreeMarker的入门文章链接。

在GreenDao中代码生成逻辑是以DaoGenerator.generateAll()作为入口。使用FreeMarker实现的生成代码的引擎。

生成代码的方式有很多种,最基础的是拼接字符串的形式实现,传入变量去拼接,然后将字符串写到一个文件中。还有一种生成代码的方式叫javapoet的,使用javapoet的语法定义文件、类、方法,然后将方法放入类中,类放入文件中,是个挺有意思的框架,有感兴趣的可以了解一下。当然还有FreeMarker类似的框架velocity,这些都是java模板引擎生成代码的框架。

大家可以学习完GreenDao生成代码之后自己去练习写一个生成代码的框架,已到达复用的目的,这也是高级工程师、架构设计师的基本技能手段。

7.相关参考

GreenDao github地址
https://github.com/greenrobot/greenDAO
Gradle插件开发
https://www.jianshu.com/p/d53399cd507b
JDT 介绍
http://www.eclipse.org/jdt/overview.php
注解处理器
https://blog.csdn.net/u013045971/article/details/53509237
自定义注解
https://blog.csdn.net/u013045971/article/details/53433874
FreeMarker 快速入门
https://segmentfault.com/a/1190000011768799

推荐阅读更多精彩内容