lombok保姆教学

初始化准备工作

所有的环境如下:

  • jdk1.8或者jdk11
  • Springboot2.x
  • mysql5.7或者mysql8.0

首先创建Springboot工程,初次创建初始化速度慢
如果想指定单个项目的maven中央仓库,pom中的配置如下:

<!-- 代码库 -->
    <repositories>
        <repository>
            <id>maven-ali</id>
            <url>http://maven.aliyun.com/nexus/content/groups/public//
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>true</enabled>
                <updatePolicy>always</updatePolicy>
                <checksumPolicy>fail</checksumPolicy>
            </snapshots>
        </repository>
    </repositories>

    <pluginRepositories>
        <pluginRepository>
            <id>public</id>
            <name>aliyun nexus</name>
            <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </pluginRepository>
    </pluginRepositories>

Lombok

Lombok简介

java工程中,我们要创建很多的java Bean。这些javaBean中都会写getter,setter,equals,hashCode和toString的模板代码,这些代码都没啥技术含量。

​ 那么我们就是使用Lombok来自动生成这些代码,通过注解的方式。提高我们的工作效率。

​ Lombok的原理:JSR 269插件化注解处理。就是在编译生成字节码之前,Lombok根据自己编写的注解处理器,动态地修改 AST增加新的节点(即Lombok自定义注解所需要生成的代码),最终生成JVM可执行的字节码Class文件。

​ 什么是JSR 269?
JSR 269: Pluggable Annotation Processing API
实现在Javac编译阶段利用“Annotation Processor”对自定义的注解进行预处理后生成真正在JVM上面执行的“Class文件

  • java反射技术的对比
    • 使用Annotation Processing自定义注解是在编译阶段进行修改
    • JDK的反射技术是在运行时动态修改

结论:反射更加灵活一些但是带来的性能损耗更加大

安装

  • 安装插件。在idea工具中安装Lombok插件,安装完成后重启idea
  • 添加依赖
 <!--scope=provided,说明它只在编译阶段生效,不需要打入包中, Lombok在编译期将带Lombok注解的Java文件正确编译为完整的Class文件-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.16</version>
            <scope>provided</scope>
        </dependency>

开启 annotation processing,重启idea
lombok保姆教学_第1张图片

@getter和@setter注解

  • 作用
    • 生成对应的getter和setter方法
  • 使用方法
    • 写在对应的属性上,生成此属性的getter和setter
    • 写在类上,生成所有属性的getter和setter
    • 方法控制访问级别 set和get注解加上 @Getter(AccessLevel.PROTECTED)
    • 不想生成set、get方法@Getter(AccessLevel.NONE)
    • 常量(final)只生成getter
    • 静态变量不生成getter和setter
  • 代码如下
    具体效果可以先compile,然后在idea中查看对应的字节码文件。
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;

import java.util.Date;

@Getter
@Setter
public class User {

    // 生成私有的getter
    @Getter(AccessLevel.PRIVATE)
    private int id;

    // 不生成setter
    @Setter(AccessLevel.NONE)
    private String username;

    private String pwd;

    private String phone;

    private String email;

    private Date createTime;

    // final 没有setter
    private final String status = "启动";

    // static 没有getter和setter
    private static String address = "河南洛阳";

}

@NonNull注解

  • 作用:作用于方法上或者属性,用于非空判断,如果为空则抛异常
  • 代码
	@NonNull
    private String pwd;

	public void login(@NonNull String pwd){
        System.out.println("登录");
    }

构造方法相关注解

  • @NoArgsConstructor
    • 生成无参构造器
  • @AllArgsConstructor
    • 生成全参构造器
    • final和static属性不生成
  • @RequiredArgsConstructor
    • 指定参数的构造函数,有以下的特征的字段
      • final类型未被初始化的属性, 标记了@NonNull的属性
      • 标记了@NonNull的属性
    • 注意:自定义的构造函数不要冲突,主要是类型
    • 理解此注解,需要结合final关键字的含义
    • @NoArgsConstructor不能加

@ToString注解

  • 作用:重写toString方法,方便调试。
  • 使用:写在类名上
    • 默认输出所有属性
    • 不包含某个属性
    • 只输入指定属性
//不包含某个属性
@ToString(exclude = {"age"})
//只输入指定属性
@ToString(of = {"name"})

@EqualsAndHashCode注解

作用:@EqualsAndHashCode注解可以重写对象的HashCode方法和equals方法
我们先来了解下这两个方法:

  • HashCode⽅法
    • 顶级类Object⾥⾯的⽅法,所有类都是继承Object的,返回值int类型
    • 根据⼀定的hash规则(存储地址,字段,或者⻓度等),映射成⼀个数值,即散列值
  • Equals⽅法
    • 顶级类Object⾥⾯的⽅法,所有类都是继承Object的,返回值boolean类型
    • 根据⾃定义的匹配规则,⽤于匹配两个对象是否⼀样, ⼀般逻辑是如下
   //判断地址是否⼀样
  //⾮空判断和class类型判断
  //强转
  //对象⾥⾯的字段⼀⼀匹配

那为什么要对比这么多内容?

如果两个对象相等,那么它们的hashCode()值一定相同(这里的相等是指,通过equals()比较两个对象时返回true)

如果两个对象hashCode()相等,它们并不一定相等。在散列表中hashCode()相等,即两个键值对的哈希值相等。
然而哈希值相等,并不一定能得出键值对相等,就出现所谓的哈希冲突场景,还需判断equals⽅法判断对象是否相

应用场景:

​ 当向集合中插⼊对象时,如何判别在集合中是否已经存在该对象,⽐如Set确保存储对象的 唯⼀,并判断是不是同个对象呢?

依据hashCode和equals进⾏判断
所以Set存储的对象必须重写这两个⽅法 判断两个对象是否⼀样
⾸先判断插⼊obj的hashcode值是否存在,hashcode值不存在则直 接插⼊集合
值存在则还需判断equals⽅法判断对象是否相等

接下来看一段代码:

 Set<User> set = new HashSet<>();
        User u1 = new User("123456");
        User u2 = new User("123456");
        System.out.println(u1==u2); // 返回false,在内存中的地址是不一样的
        set.add(u1);
        set.add(u2);
        System.out.println(set.size()); // 长度为2,表示两个都添加成功

然后在User中添加@EqualsAndHashCode注解,还是运行上面的代码,发现长度为1。

使用:

  • 作用于类,覆盖默认的equals和hashCode, 作用于全部属性
  • 不包括某个属性
@EqualsAndHashCode(exclude = {"age"})
  • 只输出某个属性
@EqualsAndHashCode(of = {"name"})

@Data注解

Lombok前面讲了多个注解,一个个加也麻烦

  • @Data, 定义一个干净的类,增加此注解,mvn compile查看字节码
  • 作用于类上,是以下注解的集合
    • @ToString
    • @EqualsAndHashCode
    • @Getter
    • @Setter
    • @RequiredArgsConstructor

@Builder注解

构造者模式:又称之为建造者模式

  • 场景:当一个bean类重载了多个构造方法时,并且参数随机使用时,考虑使用构造者模式
  • 代码
@Data
@Builder
public class Student {
    private int id;

    private String username;

    private String pwd="";

    private final String phone="";

    private String email;

    private Date createTime;

    // final 没有setter
    private final String status = "启动";

    // static 没有getter和setter
    private static String address = "河南洛阳";
}
Student student = Student.builder().id(123).pwd("1").username("张三").build();

@Log和@Slf4j注解

  • @Log / @Slf4j
    • 作用于类上,生成日志变量, 用于记录日志
  • 如果不生效,记得检查下面的配置,另外重新更新下lombok插件,重启idea
    • 开始按照创建的那边,记得开启 开启annotion processing
  • 使用
@Slf4j
public class StudentDO {
    public void test(String email){

        log.info("test方法测试");
        this.email = email;
    }
}

//字节码
public class StudentDO {
    private static final Logger log = Logger.getLogger(StudentDO.class.getName());
}

你可能感兴趣的:(Lombok)