什么是Lombok?
Project Lombok is a java library that automatically plugs into your editor and build tools, spicing up your java.Never write another getter or equals method again, with one annotation your class has a fully featured builder, Automate your logging variables, and much more.
简而言之:lombok是一个快速高效开发的工具。或者说:lombok主要是一系列用于快速开发的注解。
lombok原理:在程序源代码中植入相关注解,在javac编译时(而不是运行时)动态添加相关逻辑代码修改语法树,生成
最终的Class字节码文件。
注:关于javac编译过程编译原理,笔者后面会抽时间进行学习并分享,今天主要以学习lombok的使用为主。
start!!!
本人测试时软硬件环境:Windows10、IntelliJ IDEA、SpringBoot 2.1.1.RELEASE
准备工作:
第一步:引入lombak依赖
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.4</version>
<scope>provided</scope>
</dependency>
第二步:让IDE认识lombok
说明:因为lombok是编译时才会产生相应的代码,在源文件里是没有相应代码的,这时如果想使用生成的代码或者
触发开发工具的相关check功能,就有可能会报黄或报红;为了解决这个问题,我们需要安装插件,使IDE认
识lombok。
IntelliJ IDEA安装lombok插件示例:
注:安装插件后,需要重启IntelliJ IDEA才会生效。
lombok各注解使用示例
@Getter注解:
注解 | 功能 | 作用范围 | 所含属性 | 属性值类型 | 属性说明 | 注意事项 |
@Getter | 自动产生属性的getter方法 | FIELD、TYPE | value | lombok.AccessLevel | 设置所生成的getter方法的访问级别 注:默认值为lombok.AccessLevel.PUBLIC | @Getter放在类上,并不会生成静态属性的getter方法;而如果将@Getter直接放在静态属性上,那么即便是静态属性也会生成getter方法 |
onMethod | AnyAnnotation[] | 当需要在生成的方法上添加注解时,可通过此属性来设置 注:默认值为{}。 | ||||
lazy | boolean | 采使用用AtomicReference<V>来封装属性,保证多线程情况下的原子操作;不过仍然需要考虑ABA问题。 注:被此属性修饰的字段必须是private final的字段。 注:默认值为false。 |
注:不含内部注解。
示例源码:
编译后:
@Setter注解:
注解 | 功能 | 作用范围 | 所含属性 | 属性值类型 | 属性说明 | 注意事项 |
@Setter | 自动产生属性的setter方法 | FIELD、TYPE | value | lombok.AccessLevel | 设置所生成的setter方法的访问级别 注:默认值为lombok.AccessLevel.PUBLIC | @Setter放在类上,并不会生成静态属性的setter方法;而如果将@Setter直接放在静态属性上,那么即便是静态属性也会生成setter方法 |
onMethod | AnyAnnotation[] | 当需要在生成的方法上添加注解时,可通过此属性来设置 注:默认值为{}。 | ||||
onParam | AnyAnnotation[] | 当需要在生成的方法的形参前添加注解时,可通过此属性来设置 注:默认值为{}。 |
注:不含内部注解。
示例源码:
编译后:
@ToString注解:
注解 | 功能 | 作用范围 | 所含属性 | 属性值类型 | 属性说明 |
@ToString | 自动重写toString方法 | TYPE | includeFieldNames | boolean | toString方法是否输出字段名。 注:如果为false将只输出字段值。 注:默认值为true |
exclude | String[] | toString时将哪些属性除开 注:默认值为{}。 | |||
of | String[] | 指定toString输出哪些字段。 注:默认输出所有非静态属性。 | |||
callSuper | boolean | 是是否连父类的字段也一块儿toString输出 注:默认值为false。 | |||
doNotUseGetters | boolean | toString方法中,获取属性值时;是否不使用getter方法,而直接通过this.属性名来获取属性值
注:默认值为false,即:默认使用getter方法获取属性值 | |||
onlyExplicitlyIncluded | boolean | toString输出时,只输出被@ToString.Include注解标识了的字段 注:与of属性功能类似 注:默认值为false,即:默认输出所有非静态属性。 |
注:不含内部注解。
示例(部分):
@EqualsAndHashCode注解:
注解 | 功能 | 作用范围 | 所含属性 | 属性值类型 | 属性说明 |
@EqualsAndHashCode | 自动重写equals和hashCode方法 | TYPE | exclude | String[] | 重写的equals和hashCode方法中,将哪些属性除开 注:默认值为{}。 |
of | String[] | 指定equals和hashCode方法包含哪些字段。 注:默认包含all (non-static, non-transient) fields。 | |||
callSuper | boolean | 是否连父类的字段也一块儿equals和hashCode 注:默认值为false。 | |||
doNotUseGetters | boolean | equals和hashCode方法中,获取属性值时;是否不使用getter方法,而直接通过this.属性名来获取属性值
注:默认值为false,即:默认使用getter方法获取属性值 | |||
onlyExplicitlyIncluded | boolean | 指定equals和hashCode方法包含只包含被@EqualsAndHashCode.Include注解标识了的字段 注:与of属性功能类似 注:默认值为false,即:包含all (non-static, non-transient) fields。 | |||
onParam | AnyAnnotation[] | 当需要在生成的方法的形参前添加注解时,可通过此属性来设置 注:默认值为{}。 |
注:不含内部注解。
示例源码:
编译后:
@NonNull注解:
注解 | 功能 | 作用范围 | 说明 |
@NonNull | 非空检验 | FIELD、METHOD、PARAMETER、LOCAL_VARIABLE、TYPE_USE | 功能性注解,只有有和没有之分 |
示例源码:
编译后:
日志相关注解:
注解 | 功能 | 作用范围 | 所含属性 | 属性值类型 | 属性说明 |
@CommonsLog | 获取一个logger字段,用来记录日志 注:这往往需要相关的日志配置文件,如:logback-spring.xml | TYPE | topic | String | 指定一name,来获取Logger实例 注:详见重载方法 public static Logger getLogger(String name) 注:默认为当前注解所标识的类 |
@Log | |||||
@JBossLog | |||||
@Log4j | |||||
@Log4j2 | |||||
@Slf4j | |||||
@XSlf4j | |||||
@Flogger | 无 | 无 | 无 |
示例源码:
编译后:
构造器相关注解:
注解 | 功能 | 作用范围 |
@NoArgsConstructor | 无参构造 | TYPE |
@AllArgsConstructor | 全参构造 注:主要针对于实例属性 | |
@RequiredArgsConstructor | 有参构造,当获取实例时,需要某个参数不能为null时,可使用此构造指定 注:主要针对于实例属性 |
构造器注解的相关属性有:
三个构造器所涉及的属性汇总 | 属性值类型 | 属性说明 |
staticName | String | 生成一个名为staticName值的静态方法,获取类的实例 注:默认值为"" |
onConstructor | AnyAnnotation[] | 如果需要在生成的构造方法上添加注解,可在此处设置 注:默认值为{} |
access | AccessLevel | 设置生成的方法的访问级别 注:默认值为lombok.AccessLevel.PUBLIC |
force | boolean | 我们知道:被final修饰的成员变量,必须程序员主动赋予初始值。当force属性值为true时,被final修饰的成员变量可以无需程序员主动赋值,lombok在编译时,检车到有未初始化的fianl修饰的成员变量时,会自动赋予相应的值(null/0/false) 注:force属性值默认为false |
示例源码:
编译后:
注:如果类中没有其它构造器的话,那么写不写@NoArgsConstructor都是一样的,因为默认就会有无参构造。
@RequiredArgsConstructor的神仙用法:
我们知道,在自动装配对象时,不推荐这样的方式(方式一):
推荐这样的方式(方式二):
使用@RequiredArgsConstructor或@RequiredArgsConstructor(onConstructor = @__(@Autowired))进一步优化,是这样的(方式三):
注:方式三通过lombok生成的代码,与方式二其实是一模一样的(感兴趣的可以反编译看一下代码)。
提示一:相比起@RequiredArgsConstructor生成的构造器,@RequiredArgsConstructor(onConstructor = @__(@Autowired))
生成的构造器会在构造方法上多一个@Autowired注解,如:
如果该类本身就是交由Spring管理的(即:Ioc的),那么在构造方法上加@Autowired注解是可以省略的,所以这种
情况下,@RequiredArgsConstructor和@RequiredArgsConstructor(onConstructor = @__(@Autowired))
可以说是等效的。
提示二:使用@RequiredArgsConstructor时,构造器中会对那些没有初始值的final变量赋值,如果final变量已经有初始值了,
那么构造器里面是不会再对该变量进行赋值的,如:
上图代码编译后:
@Synchronized注解:
注解 | 功能 | 作用范围 | 所含属性 | 属性值类型 | 属性说明 |
@Synchronized | 将目标方法中的代码放入synchronized同步代码块儿 | METHOD | value | String | 指定使用某个锁 |
示例源码:
编译后:
@Data注解:
注解 | 功能 | 作用范围 | 所含属性 | 属性值类型 | 属性说明 |
@Data | 等同于 放在类上的@Getter + 放在类上的@Setter + @ToString + @EqualsAndHashCode | TYPE | staticConstructor | String | 生成一个指定名字的方法,以获取实例对象 注:同时,构造方法会置为private |
示例源码:
编译后:
@Cleanup注解:
注解 | 功能 | 作用范围 | 所含属性 | 属性值类型 | 属性说明 |
@Cleanup | 自动关闭流 | LOCAL_VARIABLE | value | String | 所谓自动关闭流,只不过是通过调用value的值对应的方法来关闭流的,而其默认值为 “close”,对应closs()方法 |
示例源码:
编译后:
@SneakyThrows注解:
注解 | 功能 | 作用范围 | 所含属性 | 属性值类型 | 属性说明 |
@SneakyThrows | Sneaky异常 | METHOD、CONSTRUCTOR | value | Class<? extends Throwable>[] | 捕获指定的异常,并抛出 注:默认值为java.lang.Throwable.class |
示例源码:
编译后:
@Value注解:
注解 | 功能 | 作用范围 | 所含属性 | 属性值类型 | 属性说明 |
@Value | 等同于 方在类上的@Getter + @AllArgsConstructor + @ToString + @EqualsAndHashCode | TYPE | staticConstructor | String | 生成一个指定名字的静态方法,以获取实例对象注:同时,构造方法会置为private |
示例源码:
编译后:
@Builder注解:
说明:通过@Builder注解,可自动为我们创建类的建造者模式,非常方便。
示例源码:
编译后等价于:
注:@Builder注解还有很多属性,如:通过设置builderMethodName属性的值,可以修改builder方法的方法名;
通过设置buildMethodName属性的值,可以修改build方法的方法名;通过设置builderClassName属性的值,
可以修改成员建造者内部类的类名等等;更多详见源码。
注:@Builder注解只是为类制造了一个创建者,所以我们还需要给类编写getter、setter方法等;所以@Builder注
解一般和@Data注解或@Getter、@Setter注解等搭配使用。
获取被@Builder注解标注了的User类示例:
val、var自动识别类型:
示例源码:
编译后:
注:官方文档里面说val与var的区别在于,生成代码后,val对应的的变量是有final修饰的,而var对应的的变量
则没有;但反编译查看发现两者效果一样,估计是此版本(1.18.4)的bug。
注:lombok还有一些注解,这里就不一一举例了。感兴趣的可查阅相关资料。
总结:
- @Getter、@Setter、@NonNull、获取Logger实例的注解 相对实用
- 笔者更喜欢IntelliJ IDEA自带的重写toString的功能,因为其比@ToString面相优雅
- 使用IntelliJ IDEA自带的重写equals、hashCode的功能还是使用@EqualsAndHashCode区别不大
- try with resources貌似比@Cleanup关闭流更方便
- @SneakyThrows貌似没什么用,不排除预留作拓展
- val与var,这是准备强类型语言向弱类型语言转换吗。不过貌似Lombok1.18.4版本有bug。