Lombok有什么用

在我们实体Bean中有大量的Getter/Setter方法以及toStringhashCode等可能不会用到,但是某些时候仍然需要复写;在使用Lombok之后,将由其来自动帮你实现代码生成。注意,其是在编译源码过程中,帮你自动生成的。就是说,将极大减少你的代码总量。

Lombok的官方地址: https://projectlombok.org/

使用Lombok时需要注意的点

  • 在类需要序列化、反序列化时或者需要详细控制字段时,应该谨慎考虑是否要使用Lombok,因为在这种情况下容易出问题。例如:Jackson、Json序列化
  • 使用Lombok虽然能够省去手动创建settergetter方法等繁琐事情,但是却降低了源代码文件的可读性和完整性,减低了阅读源代码的舒适度
  • 使用@Slf4j还是@Log4j注解,需要根据实际项目中使用的日志框架来选择。
  • Lombok并非处处适用,我们需要选择适合的地方使用Lombok,例如pojo是一个好地方,因为pojo很单纯

Lombok的安装

eclipse安装Lombok步骤:

  1. 下载最新的lombok.jar包,下载地址:https://projectlombok.org/download.html
  2. 进入cmd窗口,切到Lombok下载的目录,运行命令: java -jar lombok.jar,会出现如下界面:
    已经默认选好了eclipse安装目录(这个可能是因为我只有一个盘,如果没有默认选择,可以自己点击下方Specify location...按钮选择eclipse安装目录),点击图中红色箭头指向的按钮,即可完成安装。成功界面如下:
  3. eclipse安装目录下的eclipse.ini文件末尾已经加了一行内容(这个路径因人而异,和eclipse安装目录有关),如下:
    而且安装目录下也多了一个lombok.jar

spring boot集成Lombok

  1. 先去http://start.spring.io/在线生成一个spring boot项目脚手架,导入eclipse。

  2. pom.xml里添加Lombok依赖:

    <dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.16.14</version>
    </dependency>
  3. src/main/java/com/example/springbootlombok/entity下新建一个student.java的Java bean:

    package com.example.springbootlombok.entity;
    
    import lombok.Data;
    
    @Data
    public class Student {
    private String name;
    private int age;
    }
  4. src/test/java/com/example/springbootlombok下新建一个TestEntity.java的测试类:

    package com.example.springbootlombok;
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.context.junit4.SpringRunner; import com.example.springbootlombok.entity.Student; import lombok.extern.slf4j.Slf4j; @RunWith(SpringRunner.class)
    @SpringBootTest
    @Slf4j
    public class TestEntity { Student student = new Student(); @Test
    public void test() {
    student.setName("张三");
    student.setAge(12);
    log.info("测试结果:" + student.toString());
    }
    }
  5. 执行JUnit测试,成功的话,日志里会有打印测试结果:Student(name=张三, age=12),至此,spring boot已经成功集成Lombok了。

Lombok常用注解

@NonNull

这个注解可以用在成员方法或者构造方法的参数前面,会自动产生一个关于此参数的非空检查,如果参数为空,则抛出一个空指针异常,举个例子:

编译前的代码:

//成员方法参数加上@NonNull注解
public String getName(@NonNull Person p) {
return p.getName();
}

编译后的代码:

public String getName(@NonNull Person p) {
if (p == null) {
throw new NullPointerException("person");
}
return p.getName();
}

@Cleanup

这个注解用在变量前面,可以保证此变量代表的资源会被自动关闭,默认是调用资源的close()方法,如果该资源有其它关闭方法,可使用@Cleanup("methodName")来指定要调用的方法,就用输入输出流来举个例子:

编译前的代码:

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[1024];
while (true) {
int r = in.read(b);
if (r == -1) break;
out.write(b, 0, r);
}
}

编译后的代码:

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();
}
}
}

@Getter/@Setter

这一对注解从名字上就很好理解,用在成员变量前面,相当于为成员变量生成对应的get和set方法,同时还可以为生成的方法指定访问修饰符,当然,默认为public,直接来看下面的简单的例子:

编译前的代码:

public class Programmer {
@Getter
@Setter
private String name; @Setter(AccessLevel.PROTECTED)
private int age; @Getter(AccessLevel.PUBLIC)
private String language;
}

编译后的代码:

public class Programmer {
private String name;
private int age;
private String language; public void setName(String name) {
this.name = name;
} public String getName() {
return name;
} protected void setAge(int age) {
this.age = age;
} public String getLanguage() {
return language;
}
}

这两个注解还可以直接用在类上,可以为此类里的所有非静态成员变量生成对应的get和set方法。

@Getter(lazy=true)

如果Bean的一个字段的初始化是代价比较高的操作,比如加载大量的数据;同时这个字段并不是必定使用的。那么使用懒加载机制,可以保证节省资源。

懒加载机制,是对象初始化时,该字段并不会真正的初始化,而是第一次访问该字段时才进行初始化字段的操作。

@ToString/@EqualsAndHashCode

这两个注解也比较好理解,就是生成toStringequalshashcode方法,同时后者还会生成一个canEqual方法,用于判断某个对象是否是当前类的实例,生成方法时只会使用类中的非静态和非transient成员变量,这些都比较好理解,就不举例子了。

当然,这两个注解也可以添加限制条件,例如用@ToString(exclude={"param1","param2"})来排除param1和param2两个成员变量,或者用@ToString(of={"param1","param2"})来指定使用param1和param2两个成员变量,@EqualsAndHashCode注解也有同样的用法。

@NoArgsConstructor/@RequiredArgsConstructor /@AllArgsConstructor

这三个注解都是用在类上的,第一个和第三个都很好理解,就是为该类产生无参的构造方法和包含所有参数的构造方法,第二个注解则使用类中所有带有@NonNull注解的或者带有final修饰的成员变量生成对应的构造方法。当然,和前面几个注解一样,成员变量都是非静态的,另外,如果类中含有final修饰的成员变量,是无法使用@NoArgsConstructor注解的。

三个注解都可以指定生成的构造方法的访问权限,同时,第二个注解还可以用@RequiredArgsConstructor(staticName="methodName")的形式生成一个指定名称的静态方法,返回一个调用相应的构造方法产生的对象,下面来看一个生动鲜活的例子:

编译前的代码:

@RequiredArgsConstructor(staticName = "sunsfan")
@AllArgsConstructor(access = AccessLevel.PROTECTED)
@NoArgsConstructor
public class Shape {
private int x;
@NonNull
private double y;
@NonNull
private String name;
}

编译后的代码:

public class Shape {
private int x;
private double y;
private String name; public Shape() {
} protected Shape(int x, double y, String name) {
this.x = x;
this.y = y;
this.name = name;
} public Shape(double y, String name) {
this.y = y;
this.name = name;
} public static Shape sunsfan(double y, String name) {
return new Shape(y, name);
}
}

@Data/@Value

@Data注解综合了@Getter/@Setter@ToString@EqualsAndHashCode@RequiredArgsConstructor注解,其中@RequiredArgsConstructor使用了类中的带有@NonNull注解的或者final修饰的成员变量,它可以使用@Data(staticConstructor="methodName")来生成一个静态方法,返回一个调用相应的构造方法产生的对象。

@Value注解和@Data类似,区别在于它会把所有成员变量默认定义为private final修饰,并且不会生成set方法。

@SneakyThrows

这个注解用在方法上,可以将方法中的代码用try-catch语句包裹起来,捕获异常并在catch中用Lombok.sneakyThrow(e)把异常抛出,可以使用@SneakyThrows(Exception.class)的形式指定抛出哪种异常,很简单的注解,直接看个例子:

编译前的代码:

public class SneakyThrows implements Runnable {
@SneakyThrows(UnsupportedEncodingException.class)
public String utf8ToString(byte[] bytes) {
return new String(bytes, "UTF-8");
} @SneakyThrows
public void run() {
throw new Throwable();
}
}

编译后的代码:

public class SneakyThrows implements Runnable {
@SneakyThrows(UnsupportedEncodingException.class)
public String utf8ToString(byte[] bytes) {
try {
return new String(bytes, "UTF-8");
} catch(UnsupportedEncodingException uee) {
throw Lombok.sneakyThrow(uee);
}
} @SneakyThrows
public void run() {
try {
throw new Throwable();
} catch(Throwable t) {
throw Lombok.sneakyThrow(t);
}
}
}

@Synchronized

这个注解用在类方法或者实例方法上,效果和synchronized关键字相同,区别在于锁对象不同,对于类方法和实例方法,synchronized关键字的锁对象分别是类的class对象this对象,而@Synchronized的锁对象分别是私有静态final对象LOCK私有final对象lock,当然,也可以自己指定锁对象,例子也很简单,往下看:

编译前的代码:

public class Synchronized {
private final Object readLock = new Object(); @Synchronized
public static void hello() {
System.out.println("world");
} @Synchronized
public int answerToLife() {
return 42;
} @Synchronized("readLock")
public void foo() {
System.out.println("bar");
}
}

编译后的代码:

public class Synchronized {
private static final Object $LOCK = new Object[0];
private final Object $lock = new Object[0];
private final Object readLock = new Object(); public static void hello() {
synchronized($LOCK) {
System.out.println("world");
}
} public int answerToLife() {
synchronized($lock) {
return 42;
}
} public void foo() {
synchronized(readLock) {
System.out.println("bar");
}
}
}

@Log

这个注解用在类上,可以省去从日志工厂生成日志对象这一步,直接进行日志记录,具体注解根据日志工具的不同而不同,同时,可以在注解中使用topic来指定生成log对象时的类名。不同的日志注解总结如下(上面是注解,下面是编译后的代码):

@CommonsLog
==> private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(LogExample.class); @JBossLog
==> private static final org.jboss.logging.Logger log = org.jboss.logging.Logger.getLogger(LogExample.class); @Log
==> private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(LogExample.class.getName()); @Log4j
==> private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(LogExample.class); @Log4j2
==> private static final org.apache.logging.log4j.Logger log = org.apache.logging.log4j.LogManager.getLogger(LogExample.class); @Slf4j
==> private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogExample.class); @XSlf4j
==> private static final org.slf4j.ext.XLogger log = org.slf4j.ext.XLoggerFactory.getXLogger(LogExample.class);

参考资料

Lombok安装及Spring Boot集成Lombok的更多相关文章

  1. 【spring boot】14.spring boot集成mybatis,注解方式OR映射文件方式AND pagehelper分页插件【Mybatis】pagehelper分页插件分页查询无效解决方法

    spring boot集成mybatis,集成使用mybatis拖沓了好久,今天终于可以补起来了. 本篇源码中,同时使用了Spring data JPA 和 Mybatis两种方式. 在使用的过程中一 ...

  2. Spring Boot集成Shrio实现权限管理

    Spring Boot集成Shrio实现权限管理   项目地址:https://gitee.com/dsxiecn/spring-boot-shiro.git   Apache Shiro是一个强大且 ...

  3. Spring Boot集成Hazelcast实现集群与分布式内存缓存

    Hazelcast是Hazelcast公司开源的一款分布式内存数据库产品,提供弹性可扩展.高性能的分布式内存计算.并通过提供诸如Map,Queue,ExecutorService,Lock和JCach ...

  4. Spring boot集成RabbitMQ(山东数漫江湖)

    RabbitMQ简介 RabbitMQ是一个在AMQP基础上完整的,可复用的企业消息系统 MQ全称为Message Queue, 消息队列(MQ)是一种应用程序对应用程序的通信方法.应用程序通过读写出 ...

  5. Spring boot 集成Dubbox(山东数漫江湖)

    前言 因为工作原因,需要在项目中集成dubbo,所以去查询dubbo相关文档,发现dubbo目前已经不更新了,所以把目光投向了dubbox,dubbox是当当网基于dubbo二次开发的一个项目,dub ...

  6. 【实验一 】Spring Boot 集成 hibernate & JPA

    转眼间,2018年的十二分之一都快过完了,忙于各类事情,博客也都快一个月没更新了.今天我们继续来学习Springboot对象持久化. 首先JPA是Java持久化API,定义了一系列对象持久化的标准,而 ...

  7. Spring Boot 集成 RabbitMQ 实战

    Spring Boot 集成 RabbitMQ 实战 特别说明: 本文主要参考了程序员 DD 的博客文章<Spring Boot中使用RabbitMQ>,在此向原作者表示感谢. Mac 上 ...

  8. spring boot集成mybatis(2) - 使用pagehelper实现分页

    Spring Boot 集成教程 Spring Boot 介绍 Spring Boot 开发环境搭建(Eclipse) Spring Boot Hello World (restful接口)例子 sp ...

  9. Spring Boot集成Jasypt安全框架

    Jasypt安全框架提供了Spring的集成,主要是实现 PlaceholderConfigurerSupport类或者其子类. 在Sring 3.1之后,则推荐使用PropertySourcesPl ...

随机推荐

  1. Linux 文本三剑客之 grep

    Linux 系统中一切皆文件. 文件是个文本.可以读.可以写,如果是二进制文件,还能执行. 在使用Linux的时候,大都是要和各式各样文件打交道.熟悉文本的读取.编辑.筛选就是linux系统管理员的必 ...

  2. 『学了就忘』Linux基础命令 — 29、关机和重启

    目录 1.sync数据同步 2.shutdown命令 3.reboot命令 4.halt和poweroff命令 5.init命令 1.sync数据同步 sync命令的基本信息如下: 命令名称:sync ...

  3. django test, app aren't loaded yet

    django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet. 解决方法: 用django的TestCase from djan ...

  4. 常见的yaml写法-CronJob

    CronJob其实就是在Job的基础上加上了时间调度,我们可以:在给定的时间点运行一个任务,也可以周期性地在给定时间点运行.这个实际上和我们Linux中的crontab就非常类似了.一个CronJob ...

  5. 九. Go并发编程--context.Context

    一. 序言 前几篇中提到 等待多个 goroutine 协作的方式可以使用WaitGroup. 但是有一种场景我们无论是使用Mutex, sync/Once,都无法满足. 场景如下 现在有一个 Ser ...

  6. 使用PAM模块实现普通用户之间su免密切换

    参考自:Allow user1 to "su - user2" without password https://unix.stackexchange.com/questions/ ...

  7. [loj3032]馕

    (直接贪心会导致分子和分母过大) 令$S_{i}=\sum_{j=1}^{L}V_{i,j}$(即其独吞整个馕的快乐度),对第$i$个人求出$n$个位置$x_{1},x_{2},...,x_{n-1} ...

  8. Map、HashMap、Properties、TreeMap

    1.掌握Map接口中常用方法. 2.遍历Map集合的两种方式都要精通. 第一种:获取所有key,遍历每个key,通过key获取value. 第二种:获取Set<Map.Entry>即可,遍 ...

  9. buu

    buuCTFwp(1~32) 1.签到题 题里就有flag flag{buu_ctf} 2.二维码 1.题目是一个二维码,用010发现提示四位数字,想到应该是暗藏压缩包 2.虚拟机foremost分离 ...

  10. Codeforces 1097G - Vladislav and a Great Legend(第二类斯特林数+树上背包)

    Codeforces 题目传送门 & 洛谷题目传送门 首先看到这题我的第一反应是:这题跟这题长得好像,不管三七二十一先把 \(k\) 次方展开成斯特林数的形式,\(f(X)^k=\sum\li ...