# Lombok 一个小巧却能有效提高编程效率的工具

# 简介

这一节, 我们来讲一个工具. 可能有人会问, 你不是讲 SpringBoot 吗? 怎么又讲起工具来了? "工欲善其事, 必先利其器" 这句话用在这儿应该再合适不过了. Lombok 是一款可以帮我我们自动生成一些固定代码的工具插件, 提高我们的编程效率的同时还能简化我们的代码.

# 简单使用

# 添加相关 jar

新建项目, 在 pom 文件中添加 jar

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
</dependency>

# idea 安装插件

我这边已经安装过了, 所以在第三步搜索的时候下方会显示相关的插件, 如果你没有安装过, 图中红框的位置会显示搜索链接, 搜到后点击安装, 然后再重启 IDEA 就可以了.

# 编码

添加类 SimpleUser.java 内容如下.

package net.abcbook.learn.lombok;

import lombok.*;

/**
 * @author summer
 * @date 2018/4/12 下午6:35
 */
/*
 * getter 方法
 * @Getter
 *
 * setter 方法
 * @Setter
 *
 * toString 方法
 * @ToString
 *
 * equalsAndHashCode
 * @EqualsAndHashCode
 *
 * @RequiredArgsConstructor
 * 生成一个包含必填参数的构造函数
 * 要与@NonNull 搭配使用,该注解修饰的属性就是必填参数
 *
 * @Data 是对上面所有的方法的整合
 */
@Data
/*
 * 空参构造
 */
@NoArgsConstructor
/*
 * 全参构造
 */
@AllArgsConstructor()
public class SimpleUser {
    private String username;
    private String password;
    private Integer age;
}

注意: 这里的代码是全部代码, 没有遗漏 gettersetter

创建测试类 LombokHelloTest.java 代码如下

/**
 * @author summer
 * @date 2018/4/12 下午6:39
 * Lombok HelloWorld 测试类
 */
@RunWith(SpringRunner.class)
@SpringBootTest
@Slf4j
public class LombokHelloTest {

    /**
     * @author summer
     * @date 2018/4/14 上午10:30
     * @return void
     * @description lombok 的 getter 和 setter 测试
     */
    @Test
    public void lombokHello(){
        SimpleUser simpleUser = new SimpleUser();
        simpleUser.setUsername("summer");

        Assert.assertEquals(simpleUser.getUsername(), "summer");

        log.info("username: " + simpleUser.getUsername());
    }

    /**
     * @author summer
     * @date 2018/4/14 上午10:30
     * @return void
     * @description lombok 的全参构造方法测试
     */
    @Test
    public void constructorTest(){
        SimpleUser simpleUser = new SimpleUser("username", "password", 18);

        Assert.assertEquals("username", simpleUser.getUsername());

        log.info("user: " + simpleUser.toString());
    }
}

运行测试方法, 测试通过.

# 代码解释

我们在测试类中使用了 SimpleUsersetUsername()getUsername() 以及全构造方法. 我们在 SimpleUser 并没有写这些方法啊, 他是哪儿来的?

答案就在类上的注释上:

  • @Data 中包含了 @Getter @Setter @ToString @EqualsAndHashCode @RequiredArgsConstructor 这几个注解
  • @Getter 表示为当前类的属性自动生成 Getter 方法
  • @Setter 表示为当前类的属性自动生成 Setter 方法
  • @ToString 表示为当前类的属性自动生成 ToString 方法
  • @ToString 表示为当前类的属性自动生成 ToString 方法
  • @EqualsAndHashCode 表示为当前类的属性自动生成 EqualsAndHashCode 方法
  • @RequiredArgsConstructor 生成一个包含必填参数的构造函数, 要与@NonNull 搭配使用,该注解修饰的属性就是必填参数

除此之外, 我们还看到在测试类 LombokHelloTest.java 有注解 @Slf4j 以及下面用到的 log.info() 方法. @Slf4j 也是 Lombok 的注解, 相当于我们在测试类通过 LoggerFactory 构造出了一个 logger . 就是在类中添加了如下代码

private Logger log = LoggerFactory.getLogger(LombokHelloTest.class);

# 含有继承的类

# 编码

添加类 BaseModel.java 代码如下

package net.abcbook.learn.lombok;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @author summer
 * @date 2018/4/13 上午9:59
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class BaseModel {
    private Long id;
}

添加类 User.java 代码如下

package net.abcbook.learn.lombok;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

/**
 * @author summer
 * @date 2018/4/13 上午10:00
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString(callSuper = true)
public class User extends BaseModel {

    private String username;
    private String password;
    private Integer age;
}

添加类 UserTest.java 代码如下

package net.abcbook.learn.lombok;

import lombok.extern.slf4j.Slf4j;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

/**
 * @author summer
 * @date 2018/4/12 下午6:39
 * 含有继承的对象, 测试类
 */
@RunWith(SpringRunner.class)
@SpringBootTest
@Slf4j
public class UserTest {

    /**
     * @author summer
     * @date 2018/4/13 上午11:02
     * @return void
     * @description 获取全参构造的测试方法
     */
    @Test
    public void allArgsConstructorTest(){
        /*
         * 在上一个例子中已经加入了一个全参构造的方法
         * 但是继承时, 能不能加上父类的参数一起生成构造方法呢? 答案是不行
         * 但是在 @ToString 和 @EquesAndHashCode 使用的时候是可以连同父类的属性一起生成的
         */
        User user = new User("username", "password", 18);
        user.setId(123L);


        Long assertId = 123L;
        Assert.assertEquals(assertId, user.getId());
    }

    /**
     * @author summer
     * @date 2018/5/28 上午10:44
     * @return void
     * @description 全参的 ToString 方法
     */
    @Test
    public void allArgsToString(){
        User user = new User("username", "password", 18);
        // 如果想使用除了全参(本类)和空参以外的其他构造方法, 则需要自己去定义
        // User user1 = new User(1231L, "username1","password1", 181);
        // 这里调用的是父类 `BaseModel` 中的 `Setter` 方法
        user.setId(123L);


        Long assertId = 123L;
        Assert.assertEquals(assertId, user.getId());

        log.info("AllArgsUser contain Super: " + user.toString());
    }
}

# 代码解释

# BaseModel.java

我们看到, 除了 id 属性以外, 还有 3 个注解 @Data, @NoArgsConstructor@AllArgsConstructor , 这里我们重点说一下 @Data. 另外两个构造方法, 因为构造方法不具有继承性, 所以就不详述了.

如果我们在这里(BaseModel类)不生成相应的 Getter Setter 方法. 那么在子类中调用的时候会出现找不到方法问题. 因为子类中无法通过 Lombok的注解生成父类中属性的 Getter Setter 方法, 也无法通过 Lombok 的相关注解构, 用父类中的属性生成构造方法.

# User.java

此类中 @ToString 注解多了一个参数 callSuper = true , 这个参数的含义是, 在生成 ToString 方法时, 会调用父类中的属性.

# UserTest.java

相关的注意点, 已经写到了代码中的注释中.

# 项目源码

SpringBoot 教程: https://github.com/lixian13149999/spring-boot-learn

对应示例项目: lombok

# 总结

Lombok 是个看似不起眼的 '小' 插件, 但在实际使用中, 他让我们的代码极为简洁. 在编辑器中隐藏了必要, 但不需要太关注的代码, 让我们能把更多的注意力放到业务中去.

上次更新时间: 2020/6/17 下午5:44:30