Lombok简介

Lombok(https://projectlombok.org/)  提供了以注解的形式为java对象增加属性和方法,这使得原来冗长的java源文件变的简洁(不需要再使用ide去生成getter和setter方法,不过ide需要插件支持才能识别lombok自动添加的getter/setter方法,因为真正的代码其实是在编译阶段添加到子节码文件中的),一些固定模板的代码也可以自动添加,例如生成Logger。详细的原理有很多分析贴,此处不再赘述,有需要可以参见附录中的链接:http://notatube.blogspot.com/2010/11/project-lombok-trick-explained.html

Lombok中自带的注解几乎涵盖了所有冗余的,但总是会有一些需要我们自己定制的需求。

研究内容

最近遇到一个情景,一些JAVA对象都需要一个映射到数据库自增ID的字段,为了避免代码冗余,让他们继承自同一个包含同一个id字段的父类似乎就可以解决问题,不同的主键还有可能是不同的数据类型,较常见的是Long,Integer和String(uuid),所以这个父类需要写成一个模板类,并且要求所有包含主键的类都要继承这个泛型父类,其实我们只是想要的只是这个类增加一个id字段,并且生成对应的getter和setter 方法就好了,与其搞成继承关系,倒不如让效法lombok,使用annotation来生成这个字段和方法。

本文探讨的内容包括:

  1. 新增一个PrimaryKey注解,接受keyName和keyType两个参数,凡是有PrimaryKey注解的类,都会自动生成一个类型是${keyType}、字段名为${keyName}的字段,并为这个字段生成getter和setter方法。

  2. 让intellij的lombok插件能够识别新的注解,可以自动提示主键字段和它的getter/setter方法,而不报编译错误

自定义注解

不仅要新建自定义注解,还要新建对应的Handler,以便编译阶段正确处理包含自定义注解的源文件。

开发环境设置

首先checkout最新的lombok代码,https://github.com/rzwitserloot/lombok.git

lombok项目目前只有基于Eclipse的debug环境配置脚本,如果是Intellij,需要自己配置一下lombok的环境,稍后会介绍。

工程中有基于ant的自动构建脚本,先运行"compile" 任务,这时会自动触发"ensureBuildDeps"这个任务,它会下载一些依赖的Jar包。Tips:中间会去下一个对应jdk版本的rt.jar文件,由于这个文件比较大,国内下载速度非常慢,建议自行翻|墙下载,放到lib目录对应java版本的文件夹下面即可。

编译成功之后,就可以跑一下"test"任务了,它会先执行"dist",在dist目录下面生成lombok的jar文件,然后执行自动测试。

新建自定义注解

注解类代码如下:

package lombok;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; /**
 * 默认以Long作为主键类型
 * Created by hoyt on 15/9/22.
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface PrimaryKey {
    Class keyType() default Long.class;
    String keyName() default "id";
}

新建HandlePrimaryKey

handler需要继承自JavacAnnotationHandler,并实现其handle方法,简述一下handle方法里的操作

  1. 判断目标注解(这里就是PrimaryKey)是否满足正确性验证

  2. 验证通过时,为被注解的类动态添加字段,字段的名称和类型都是PrimaryKey注解中的值

  3. 为新添加的字段创建getter和setter方法

handle方法的声明如下:

public void handle(AnnotationValues<PrimaryKey> annotation, JCTree.JCAnnotation ast, JavacNode annotationNode){

}

其中,annotation是lombok自定义的类型,包含了自定义的注解信息,通过如下代码,就可以获得注解中设置的具体值

        String keyName = annotation.getInstance().keyName();
        Class pk = annotation.getInstance().keyType();

在新建字段、创建getter/setter方法时,都可以直接复用lombok已有的方法和类,非常方便,贴出部分关键代码。

        JCTree.JCExpression keyType = chainDotsString(typeNode, type);
        
        JCTree.JCVariableDecl field = maker.VarDef(
                maker.Modifiers(Flags.PRIVATE),
                typeNode.toName(keyName), keyType, null);
        
        JCTree.JCVariableDecl fieldDecl = recursiveSetGeneratedBy(field, source, typeNode.getContext());         JavacNode fieldNode = injectFieldAndMarkGenerated(typeNode, fieldDecl);         new HandleGetter().generateGetterForField(fieldNode, source.pos(),  AccessLevel.PUBLIC, false);
        new HandleSetter().generateSetterForField(fieldNode, typeNode,  AccessLevel.PUBLIC);
        return true;

*如果要支持Eclipse自带的编译器,需要另外写一个handler

测试Handle

幸好lombok已经包含了测试/调试环境配置(只针对eclipse,Intellij需要自行配置)。直接运行"setupJavaOracle8TestEnvironment",就会自动配置好基于junit的测试/调试环境。这时打开"Run Configurations",就会发现Junit的测试里多了一种"RunLombokTest"...如下图所示:

实际上没有必要跑全部的junit测试,只要跑TestWithDelombok即可

lombok的单元测试是这样的:在test/transform/resource目录里,有三个文件夹,before,after-delombok和after-ejc,before中是所有测试用的java文件,而after-delombok目录中包含的则是lombok.jar参与编译后生成的java源文件,单元测试时,会将after-delombok中的文件作为expected value去同生成的代码做比较,如果一致就认为通过测试。因此单元测试时,在before目录中创建一个class,并为之加上自定义注解,同时在after-lombok中新建一个同名类,把预期的字段和方法写进去即可。after-ejc用于测试eclipse的java编译器结果。注:lombok在处理字段和方法时,会加上额外的标注注解。

至于Intellij,做调试相对就麻烦一点,需要打开一个intellij的新实例,新建一个项目,在这个项目中引入修改后的lombok,然后加上自定义的注解,这时会触发原来那个intellij中lombok的代码运行,此时断点就会被触发。

Intellij-lombok插件

自定义的注解已经完成,在javac时指定javaagent为新打包出来的lombok.jar即可,不过蛋疼的是,ide此时尚不能识别自定义的注解,为了能够让集成开发环境与新添加的自定义注解合作无间,还需要对Intellij的lombok插件做一番改造。

今天相关的代码见:https://git.oschina.net/hoyt/lombok.git,明天继续补完Intellij插件的工作。

Lombok自定义annotation扩展含Intellij插件的更多相关文章

  1. IntelliJ插件安装

    1. 插件管理器在线安装 在IntelliJ插件管理页面([FileàSettingsàIDE SettingsàPlugins]),点击[Browse repositories-]按钮,在搜索框内输 ...

  2. Java程序员必备的Intellij插件

    以下是我用过不错的Intellij插件 1. .ignore 地址:https://plugins.jetbrains.com/plugin/7495--ignore 生成各种ignore文件,一键创 ...

  3. Java程序员必备的Intellij插件(长期更新,截止到2018-05-03)

    善用Intellij插件可大幅提升我们的效率 以下是我用过不错的Intellij插件 1. .ignore 生成各种ignore文件,一键创建git ignore文件的模板,免得自己去写 截图:   ...

  4. 善用Intellij插件可大幅提升我们的效率

    转自 :https://www.jianshu.com/p/686ba0ae4ac2 1. .ignore 生成各种ignore文件,一键创建git ignore文件的模板,免得自己去写 截图: 2. ...

  5. (转)Bootstrap 之 Metronic 模板的学习之路 - (6)自定义和扩展

    https://segmentfault.com/a/1190000006815041 前面我们将 Metronic 的结构和源码大致浏览了一遍,Metronic 整个文件包有三百多兆,在实际项目中, ...

  6. intellij 插件的使用

    目录 intellij 插件的使用 插件的设置 插件推荐 @(目录) intellij 插件的使用 插件的设置 在 IntelliJ IDEA 的安装讲解中我们其实已经知道,IntelliJ IDEA ...

  7. 阅读笔记09-Java程序员必备的Intellij插件

    1. .ignore 生成各种ignore文件,一键创建git ignore文件的模板,免得自己去写 地址:plugins.jetbrains.com/plugin/7495--ignore 2. l ...

  8. IDEA报 : Lombok Requires Annotation Processing

    Lombok Requires Annotation Processing Annotation processing seems to be disabled for the project &qu ...

  9. 2022必须拥有Chrome扩展程序 - 浏览器插件,让你上网效率翻倍

    在Chrome网上应用店中查找扩展程序 2022必须拥有Chrome扩展程序 - 浏览器插件,让你上网效率翻倍 可扩展的Chrome Web浏览器比某些人认识的功能强大得多.您可以自定义浏览体验,使其 ...

随机推荐

  1. Linux移植之auto.conf、autoconf.h、Mach-types.h的生成过程简析

    在Linux移植之make uImage编译过程分析中分析了uImage文件产生的过程,在uImage产生的过程中,顺带还产生了其它的一些中间文件.这里主要介绍几个比较关键的文件 1.linux-2. ...

  2. qrcodenet二维码图片下扩展区域添加号段的操作

    总监安排了个任务,一个号码导出一个二维码图, 我实现了最终还能批量生成,结果主管说要在图片下边添加一行,和图片是一起的 最开始把控件的上的图给改了,结果保存起来没用,控件上的图跟要保存的不是一个事. ...

  3. (转)在WCF服务的ServiceReferences.ClientConfig中使用相对路径

    问题: Silverlight项目中添加服务引用后会在Silverlight项目中生成一个ServiceReferences.ClientConfig文件,这个文件中包含了引用服务的绑定(bindin ...

  4. 优化myeclipse启动速度以及解决内存不足问题

    解决myeclipse内存不足问题: 使用 MyEclipse 开发项目后,随着项目文件的增多,以及运行时间的增加,实际上 MyEclipse 所消耗的内存是会一直增大的,有的时候会出现 MyEcli ...

  5. 前端面试问题js汇总

    1.javascript的typeof返回哪些数据类型 Object number function boolean underfind 2,数组方法pop() push() unshift()shi ...

  6. iOS.mach_absolute_time

    1. Technical Q&A QA1398 Mach Absolute Time Units https://developer.apple.com/library/mac/qa/qa13 ...

  7. Luogu 1641[SCOI2010]生成字符串 - 卡特兰数

    Description 有$N$ 个 $1$ 和 $M$ 个 $0$ 组成的字符串, 满足前 $k$ 个字符中 $1$ 的个数不少于 $0$ 的个数. 求这样字符串的个数. $1<=M < ...

  8. TI and RI

    https://blog.csdn.net/qq_27977257/article/details/70677661 51单片机的串口,是个全双工的串口,发送数据的同时,还可以接收数据.当串行发送完毕 ...

  9. python线程池

    https://blog.csdn.net/qq_33961117/article/details/82587873#!/usr/bin/python # -*- coding: utf- -*- f ...

  10. servlet 高级知识之Listener

    Listener,顾名思义,监听器.它可以监听客户端的请求.服务端的操作等. 通过监听器,可以自动激发一些操作,比如监听在线的用户的数量.当增加一个HttpSession时,就激发sessionCre ...