lombok 的官方网址:http://projectlombok.org/
lombok作用:
lombok 提供了简单的注解的形式来帮助我们简化消除一些必须有但显得很臃肿的 java 代码。特别是相对于 POJO,光说不做不是我的风格,先来看看吧。
lombok安装:
使用 lombok 是需要安装的,如果不安装,IDE 则无法解析 lombok 注解
1、lombok的安装跟一般引用jar包没有什么区别,可以到官网上下载最新的jar包,然后导入到项目里面就好啦。
Maven添加依赖:
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.10</version>
</dependency>
</dependencies>
2、 双击下载下来的 JAR 包安装 lombok
我选择这种方式安装的时候提示没有发现任何 IDE,所以我没安装成功,我是手动安装的。如果你想以这种方式安装,请参考官网的视频。
3、Intellij idea开发非Maven项目的话,需要安装Lombok plugin(网上很多图文教程),同时设置 Setting -> Compiler -> Annotation Processors -> Enable annotation processing勾选(貌似我的没有勾选也可以使用)。
4、eclipse / myeclipse 手动安装 lombok
a. 将 lombok.jar 复制到 myeclipse.ini / eclipse.ini 所在的文件夹目录下
b. 打开 eclipse.ini / myeclipse.ini,在最后面插入以下两行并保存:
-Xbootclasspath/a:lombok.jar
-javaagent:lombok.jar
c.重启 eclipse / myeclipse
lombok使用:
lombok 提供的注解不多,可以参考官方视频的讲解和官方文档。
lombok 注解在线帮助文档:http://projectlombok.org/features/index.
列出几个比较常用的:
@NonNull: 可以帮助我们避免空指针。
使用lombok:
import lombok.NonNull;
public class NonNullExample extends Something {
private String name;
public NonNullExample(@NonNull Person person) {
super("Hello");
this.name = person.getName();
}
}
不使用lombok:
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();
}
}
@Cleanup: 自动帮我们调用close()方法。
使用lombok:
import lombok.Cleanup;
import java.io.*;
public class CleanupExample {
public static void main(String[] args) throws IOException {
@Cleanup InputStream in = new FileInputStream(args[0]);
@Cleanup OutputStream out = new FileOutputStream(args[1]);
byte[] b = new byte[10000];
while (true) {
int r = in.read(b);
if (r == -1) break;
out.write(b, 0, r);
}
}
}
不使用lombok:
import java.io.*;
public class CleanupExample {
public static void main(String[] args) throws IOException {
InputStream in = new FileInputStream(args[0]);
try {
OutputStream out = new FileOutputStream(args[1]);
try {
byte[] b = new byte[10000];
while (true) {
int r = in.read(b);
if (r == -1) break;
out.write(b, 0, r);
}
} finally {
if (out != null) {
out.close();
}
}
} finally {
if (in != null) {
in.close();
}
}
}
}
这里其实可以优化一点
import java.io.*; public class CleanupExample { public static void main(String[] args) throws IOException { try (InputStream in = new FileInputStream(args[0]); OutputStream out = new FileOutputStream(args[1])) { byte[] b = new byte[10000]; while (true) { int r = in.read(b); if (r == -1) break; out.write(b, 0, r); } } } }
@Getter / @Setter: 自动生成Getter/Setter方法
使用lombok:
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
public class GetterSetterExample {
@Getter @Setter private int age = 10;
@Setter(AccessLevel.PROTECTED) private String name;
}
不使用lombok:
public class GetterSetterExample {
private int age = 10;
private String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
protected void setName(String name) {
this.name = name;
}
}
@NoArgsConstructor: 自动生成无参数构造函数。
@AllArgsConstructor: 自动生成全参数构造函数。
@Data: 自动为所有字段添加@ToString, @EqualsAndHashCode, @Getter方法,为非final字段添加@Setter,和@RequiredArgsConstructor!
以下是翻译官网的材料:
下面对Lombok的简单使用方法做一下总结:
● val 这不是一个注解,用于局部变量声明,减少重复输入。
● @NotNull 作用在方法参数上的注解,用于自动生成空值参数检查。
● @Cleanup 作用在局部变量上,在作用域结束时会自动调用close方法释放资源。
● @Getter 作用在字段上,会自动生成字段的Getter;作用在类上,会自动生成该类所有非静态字段的Getter,还能控制Getter的访问级别
● @Setter 基本同上。
● @ToString 类注解,自动生成类的toString方法,可以做一些定制,比如不使用某个字段,不调用Getters等。
● @EqualsAndHashCode 类注解,自动生成类中所有非静态非瞬时字段的equals方法和hashCode方法。
● @NoArgsConstructor 类注解,自动生成一个无参构造函数。
● @AllArgsConstructor 类注解,生成一个初始化所有字段的构造函数。
● @RequiredArgsConstructor 类注解,为final字段和标记了@NotNull的字段生成构造函数。
● @Data 类注解,相当于同时应用了@Getter、@Setter、@ToString、@EqualsAndHashCode、@RequiredArgsConstructor。如果已经定义了一个构造方法,就不会再自动生成构造方法了。
● @Value 类注解,和@Data类似,但是用于不可变类型。生成的类和所有字段都设置为final,所有字段都为private,自动生成Getter但是没有Setter,会生成初始化所有字段的构造函数。相当于同时应用了final @ToString、 @EqualsAndHashCode、 @AllArgsConstructor 、@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)和 @Getter。
常用的还有一个一些Log注解,Lombok已经对常用的日志都做了工作。这里直接引用官网的介绍:
1 @CommonsLog
2 Creates private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(LogExample.class);
3 @JBossLog
4 Creates private static final org.jboss.logging.Logger log = org.jboss.logging.Logger.getLogger(LogExample.class);
5 @Log
6 Creates private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(LogExample.class.getName());
7 @Log4j
8 Creates private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(LogExample.class);
9 @Log4j2
10 Creates private static final org.apache.logging.log4j.Logger log = org.apache.logging.log4j.LogManager.getLogger(LogExample.class);
11 @Slf4j
12 Creates private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogExample.class);
13 @XSlf4j
14 Creates private static final org.slf4j.ext.XLogger log = org.slf4j.ext.XLoggerFactory.getXLogger(LogExample.class);
原理分析:
简单来讲,lombok就是在编译时对抽象语法树(AST)进行了修改来实现它的功能。要了解lombok是怎么做的,那我们需要先了解下Java语言的编译器是怎么工作的。
javac
Java的编译过程可以分成三个阶段:
1. 所有源文件会被解析成语法树。
2. 调用注解处理器。如果注解处理器产生了新的源文件,新文件也要进行编译。
3. 最后,语法树会被分析并转化成类文件。
AnnotationProcessor
JSR-269提供了一种插件式的注解处理机制,通过ServiceLoader机制可以给Java编译器插上我们自己的注解处理器。也就是说,在上述编译过程的第二阶段,是允许用户介入的。
正是通过这个机制,lombok迈出了第一步。来看下lombok的jar包,
javax.annotation.processing.Processor是个配置点,lombok的实现也就是该文件的内容如下:
lombok.core.AnnotationProcessor
也就意味着,在编译的第二阶段会执行lombok.core.AnnotationProcessor。它所做的工作就是我们上面所说的,修改AST。
lombok的缺点:
1、使用lombok虽然能够省去手动创建setter和getter方法的麻烦,但是却大大降低了源代码文件的可读性和完整性,降低了阅读源代码的舒适度。
2、在JSR-269的规范里面,并没有提供修改AST的API,那么lombok是怎么达到它的目的的?It's a total hack. Using non-public API.这是lombok的作者所说的。也就是说lombok是使用了一些内部的API,也许是通过强制类型转换也许是其他,这个后续再探讨,现在只需要明白一点,lombok有风险,使用需谨慎^_^ 如果某天发布的新版本JDK修改了那些内部API,那么我们使用了lombok的代码在那个版本的JDK上面将无法编译通过,我们就要寄希望于lombok的工程师们对lombok进行修复升级了,万一修复不了呢?总之,是个坑哈。
参考文献:
[1]http://www.blogjava.net/fancydeepin/archive/2012/07/12/lombok.html
[2]http://blog.csdn.net/dslztx/article/details/46715803
[3]http://www.cnblogs.com/holten/p/5729226.html
[4]http://www.myexception.cn/program/1821190.html
[5]http://blog.csdn.net/u011054333/article/details/54381850