Lombok自定义annotation扩展含Intellij插件
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来生成这个字段和方法。
本文探讨的内容包括:
新增一个PrimaryKey注解,接受keyName和keyType两个参数,凡是有PrimaryKey注解的类,都会自动生成一个类型是${keyType}、字段名为${keyName}的字段,并为这个字段生成getter和setter方法。
让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方法里的操作
判断目标注解(这里就是PrimaryKey)是否满足正确性验证
验证通过时,为被注解的类动态添加字段,字段的名称和类型都是PrimaryKey注解中的值
为新添加的字段创建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插件的更多相关文章
- IntelliJ插件安装
1. 插件管理器在线安装 在IntelliJ插件管理页面([FileàSettingsàIDE SettingsàPlugins]),点击[Browse repositories-]按钮,在搜索框内输 ...
- Java程序员必备的Intellij插件
以下是我用过不错的Intellij插件 1. .ignore 地址:https://plugins.jetbrains.com/plugin/7495--ignore 生成各种ignore文件,一键创 ...
- Java程序员必备的Intellij插件(长期更新,截止到2018-05-03)
善用Intellij插件可大幅提升我们的效率 以下是我用过不错的Intellij插件 1. .ignore 生成各种ignore文件,一键创建git ignore文件的模板,免得自己去写 截图: ...
- 善用Intellij插件可大幅提升我们的效率
转自 :https://www.jianshu.com/p/686ba0ae4ac2 1. .ignore 生成各种ignore文件,一键创建git ignore文件的模板,免得自己去写 截图: 2. ...
- (转)Bootstrap 之 Metronic 模板的学习之路 - (6)自定义和扩展
https://segmentfault.com/a/1190000006815041 前面我们将 Metronic 的结构和源码大致浏览了一遍,Metronic 整个文件包有三百多兆,在实际项目中, ...
- intellij 插件的使用
目录 intellij 插件的使用 插件的设置 插件推荐 @(目录) intellij 插件的使用 插件的设置 在 IntelliJ IDEA 的安装讲解中我们其实已经知道,IntelliJ IDEA ...
- 阅读笔记09-Java程序员必备的Intellij插件
1. .ignore 生成各种ignore文件,一键创建git ignore文件的模板,免得自己去写 地址:plugins.jetbrains.com/plugin/7495--ignore 2. l ...
- IDEA报 : Lombok Requires Annotation Processing
Lombok Requires Annotation Processing Annotation processing seems to be disabled for the project &qu ...
- 2022必须拥有Chrome扩展程序 - 浏览器插件,让你上网效率翻倍
在Chrome网上应用店中查找扩展程序 2022必须拥有Chrome扩展程序 - 浏览器插件,让你上网效率翻倍 可扩展的Chrome Web浏览器比某些人认识的功能强大得多.您可以自定义浏览体验,使其 ...
随机推荐
- 在Qt(C++)中与Python混合编程
一.PythonQt库 在Qt(C++)中与Python混合编程,可以使用PythonQt库. 网站首页:http://pythonqt.sourceforge.net 下载页面:https://so ...
- Kali Linux 网络扫描秘籍
第三章 端口扫描(二) 作者:Justin Hutchens 译者:飞龙 协议:CC BY-NC-SA 4.0 3.6 Scapy 隐秘扫描 执行 TCP 端口扫描的一种方式就是执行一部分.目标端口上 ...
- Scrapy框架——CrawlSpider类爬虫案例
Scrapy--CrawlSpider Scrapy框架中分两类爬虫,Spider类和CrawlSpider类. 此案例采用的是CrawlSpider类实现爬虫. 它是Spider的派生类,Spide ...
- Java的OOP三大特征之一——继承
Java的OOP三大特征之一——继承 子类继承父类的特征和行为(属性和方法),使得子类具有父类的各种属性和方法.或子类从父类继承方法,使得子类具有父类相同的行为. 特点:在继承关系中,父类更通用.子类 ...
- PS故障风海报制作技术分享
1.首先找一张看起来很酷的图(也可以选择自己喜欢的图片): 2. 复制图层,点击添加图层样式,选择混合选项,在高级混合里面的通道选项,有R.G.B三个通道选项,默认是全部勾选的状态,选择其中一个勾掉( ...
- 超全面!UI设计师如何适配2018新款iPhone
北京时间9月13日凌晨1点,苹果在美国加利福尼亚州的Apple Park园区召开了2018年苹果秋季新品发布会. 很多人对这次科技界的春晚充满了期待,除了那些让人“剁手”的新品,设计师关注的还有新手机 ...
- HTTP 1.0 Status Code Definitions
part of Hypertext Transfer Protocol -- HTTP/1.1RFC 2616 Fielding, et al. 10 Status Code Definitions ...
- mysql如何查看自己数据库文件所在的位置
mysql如何查看自己数据库文件所在的位置 C:\Program Files\MySQL\MySQL Server 5.5 mysql数据库 方法/步骤 第1步: 打开mysqml文件夹,显示 ...
- robot framework 中should be true 与should contain 的区别
should be true 是否等于:判断是否should contain 是否包含 a是否包含b
- tomcat+servlet例子
在C:\Program Files\Apache Software Foundation\Tomcat 7.0\webapps\app\WEB-INF文件夹下建立文件夹classes. 在C:\Pro ...