简介
github 地址 rzwitserloot/lombok
使用
-
idea/eclipse 安装插件,因为引入lombok 注解后
- 代码与完整 版本代码相比有缺失,比如使用setter/getter 注解顶替 实际的setter/getter 方法,然后在其它位置 调用 代码上不存在的setter/getter 方法不报错
- 在代码中 使用一些java 原不存在的关键字
因为lombok 有点破坏了代码完整性,所以一些工程师不太乐意用lombok
-
引入jar
org.projectlombok lombok 1.16.14
连猜带分析,依赖jar的作用有两个
- 提供代码中使用的注解等
- 提供 javac 编译代码时 需要运行的回调
代码示例
import lombok.Getter;
import lombok.Setter;
@Setter
@Getter
public class User {
private String id;
private String name;
}
public class UserTest {
@Test
public void test() {
User user = new User();
user.setName("lisi");
System.out.println(user.getName());
}
}
实现原理
- 背景 JSR 269: Pluggable Annotation Processing API。 注解在JDK5.0及以后版本引入,最开始只能在运行时通过反射来获取注解值。 JSR 269 之后我们可以在 Javac的编译期 使用注解,自定义注解 + 自定义的annotation processor 就很有想象力了
按照jdk-compilation-overview 中的解释,java 编译过程如下
This process is handled by the JavaCompiler class.
- All the source files specified on the command line are read, parsed into syntax trees, and then all externally visible definitions are entered into the compiler’s symbol tables.
- All appropriate annotation processors are called(lombok 便是提供了一些annotation processor). If any annotation processors generate any new source or class files, the compilation is restarted, until no new files are created.
- Finally, the syntax trees created by the parser are analyzed and translated into class files. During the course of the analysis, references to additional classes may be found. The compiler will check the source and class path for these classes; if they are found on the source path, those files will be compiled as well, although they will not be subject to annotation processing.
通过lombok 扩展了以下认知
- 不仅运行期 基于aop实现自定义注解,编译期 也可以使用注解信息
- 不仅运行期(比如asm 以及基于asm的cglib),编译器 也可以动态生成/更改字节码
- 考虑到scala 也是基于 jvm运行 ==> scala 会被编译为字节码文件,scala 的很多效果也可以 挪到 java 中使用,并且lombok 确实做了一部分
Lombok原理分析与功能实现 抛开lombok,自定义一个针对类的Getter注解,它能够读取该类的成员方法并自动生成getter方法。管中窥豹 了解下 lombok 的实现原理。
使用进阶(根据实践徐徐补充)
初步的感觉就是,凡是idea 能够帮你自动生成的那些程式化代码,都可以使用lombok 代劳。
- 代码生成,比如空值检查、最外围的try catch 替换等
- 方法生成,比如包含所有参数的构造方法、toString、Builder模式的字段设置 函数
- 字段生成,比如log4j
- 关键字,比如val 等
@NonNull
public class NonNullExample extends Something {
private String name;
public NonNullExample(@NonNull Person person) {
super("Hello");
this.name = person.getName();
}
}
翻译成 Java 程序是:
public class NonNullExample extends Something {
private String name;
public NonNullExample(@NonNull Person person) {
super("Hello");
if (person == null) {
throw new NullPointerException("person");
}
this.name = person.getName();
}
}
@Slf4j
@Slf4j
public class LogExampleOther {
public static void main(String... args) {
log.error("Something else is wrong here");
}
}
翻译后:
public class LogExample {
private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(LogExample.class.getName());
public static void main(String... args) {
log.error("Something's wrong here");
}
}