Spring 的@FieldDefaults和@Data:Lombok 注解以实现更简洁的代码

介绍

作为 Java 开发人员,我们经常发现自己陷入了样板代码的困境。访问器方法、修改器方法、构造函数、equals()、hashCode()和toString()是必不可少的,但会占用大量空间并分散对应用程序核心逻辑的注意力。Spring 框架广泛用于构建企业应用程序,是减少样板文件的爱好者。然而,即使使用 Spring,一定程度的问题也是不可避免的——除非我们将 Project Lombok 引入其中。

Project Lombok 提供的注释可以大大减少样板代码,提高可读性和可维护性。在这些注释中,@FieldDefaults和@Data是常用的,本文将深入研究这两个注释,展示它们在 Spring 应用程序中的有用性。

Lombok 简介

Project Lombok 是一个库,它通过减少开发人员经常需要编写的重复和平凡的代码,对 Java 生态系统产生了重大影响。虽然 Java 是一种功能强大且用途广泛的语言,但它经常因其冗长而受到批评,尤其是与 Kotlin 或 Python 等更现代的语言相比。开发人员经常必须编写大量“仪式性”代码,只是为了让简单的事情正常工作,例如创建普通旧 Java 对象 (POJO) 及其关联的 getter、setter、 、equals()和hashCode()方法toString()。

Lombok 旨在解决什么问题

Java 的冗长不仅是美观的问题,也是一个问题。它可以直接影响开发团队的生产力。编写样板代码非常耗时,并且会增加出错的可能性。想象一个具有许多字段的类,每个字段都需要自己的 getter 和 setter 方法。这种情况很快就会变成维护噩梦,特别是当您开始添加诸如equals()和 之类的方法时hashCode(),这些方法应该彼此一致并在每次类字段更改时更新。

这就是Lombok发挥作用的地方。通过提供一组注释,Lombok 在编译时自动生成代码,避免了冗长和潜在的人为错误。最终结果是一个更具可读性和可维护性的代码库,更容易理解、调试和扩展。

Lombok 如何运作

Lombok 通过利用 Java 编译器中提供的注释处理工具来工作。编译代码时,Lombok 会扫描其注释。找到它们后,它会生成相应的代码,并将其合并到您的.class文件中。本质上,Java 编译器看到的类版本看起来像是您手动编写了所有样板代码,即使您实际上并未编写它。

这种操作方法既有优点也有缺点。从好的方面来说,您不必担心与基于反射的方法相关的运行时开销。不利的一面是,生成的代码在源文件中不可见,这对于那些不熟悉 Lombok 的人来说可能会感到困惑。

在您的项目中设置 Lombok

将 Lombok 集成到 Spring 项目中是一个简单的过程。如果您使用 Maven,则可以将以下依赖项添加到您的pom.xml:

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.22</version> <!-- Use the latest version -->
</dependency>
或者,如果您使用 Gradle,请将其包含在您的build.gradle:
dependencies {
    compileOnly 'org.projectlombok:lombok:1.18.22' // Use the latest version
    annotationProcessor 'org.projectlombok:lombok:1.18.22'
}

您还需要在 IDE 中安装 Lombok 插件,以确保它能够识别 Lombok 注释并在编译时生成适当的代码。

流行的Lombok注释

Lombok 提供了各种旨在满足不同目的的注释。以下是一些受欢迎的:

  1. @Getterand @Setter:自动生成字段的getter和setter方法。

  2. @ToString:生成人类可读的toString()方法。

  3. @EqualsAndHashCode:根据类中的字段生成equals()和方法。hashCode()

  4. @AllArgsConstructor,@NoArgsConstructor,@RequiredArgsConstructor:生成具有不同配置的构造函数。

然而,这篇文章的重点将放在@FieldDefaults和@Data注释上,它们在 Spring 应用程序的上下文中非常有用。

注释@Data

Lombok 项目的@Data注释本质上是 Java 类的一把瑞士军刀。使用单个注释,您可以自动生成各种方法,否则您必须手动创建这些方法,这些方法通常很简单,但很快就会使您的代码库变得混乱。其中包括 getter 和 setter 方法、equals()、hashCode()和toString()方法。虽然有些人可能认为“一刀切”的方法并不适合所有情况,但不可否认的是,这@Data在许多情况下都非常有用,特别是对于 POJO(在应用程序中充当数据载体的普通旧 Java 对象)。

解剖学@Data

当您使用 注释类时@Data,Lombok 会生成:

  1. 所有非静态字段的 Getter 方法

  2. 所有非最终、非静态字段的 Setter 方法

  3. equals()检查逐个字段相等性的方法

  4. 一种hashCode()根据字段计算哈希码的方法

  5. toString()返回对象的字符串表示形式的方法

该注释使用其他 Lombok 注释(例如@Getter、@Setter、@ToString和 )进行元注释@EqualsAndHashCode。因此,使用@Data相当于同时使用所有这些注释。

这是一个简单的例子来说明它的@Data作用。

没有Lombok:

public class Book {
    private String title;
    private String author;
    private int pages;

    public Book() {
    }

    public Book(String title, String author, int pages) {
        this.title = title;
        this.author = author;
        this.pages = pages;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public int getPages() {
        return pages;
    }

    public void setPages(int pages) {
        this.pages = pages;
    }

    @Override
    public boolean equals(Object o) {
        // Implementation
    }

    @Override
    public int hashCode() {
        // Implementation
    }

    @Override
    public String toString() {
        // Implementation
    }
}

Lombok的@Data:

 import lombok.Data;
@Data
public class Book {
    private String title;
    private String author;
    private int pages;
}

权衡和考虑因素

虽然@Data它是一个强大的工具,但有必要了解它的局限性并考虑何时使用它或避免它。

  1. 性能:对于大型类或复杂的层次结构,自动生成的equals()方法hashCode()可能效率低下。在这种情况下,自定义实现可能会更好。

  2. 不变性:@Data为所有非最终字段生成 setter,使类可变。如果要求不变性,您可能不想使用此注释或考虑将其与 结合使用@FieldDefaults以使字段成为最终字段。

  3. 开销:使用@Data,很容易忘记幕后发生的事情。不熟悉 Lombok 的开发人员可能会发现使用那些重要功能隐藏在单个注释后面的类会很混乱。

定制行为

Lombok 提供了自定义@Data. 例如,您可以通过用 标记来从生成的equals()和方法中排除某些字段。同样,您可以通过使用不想包含的字段来自定义表示形式。hashCode()

@EqualsAndHashCode.ExcludetoString()

@ToString.Exclude

import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;

@Data
public class CustomBook {
    private String title;
    private String author;

    @EqualsAndHashCode.Exclude
    @ToString.Exclude
    private int pages;
}

在该修改示例中,该pages字段被排除在equals()和hashCode()方法以及该toString()方法之外。

总之,@Data对于任何 Java 开发人员的工具包,特别是那些使用 Spring 框架的开发人员来说,注释都是一个非常通用的工具。通过消除样板代码,它允许您编写更简洁和可读的代码,尽管它确实有一些您需要仔细考虑的权衡。

注释@FieldDefaults

讨论较少但同样强大的 Lombok 注释之一是@FieldDefaults. 此注释提供了一种为类中的字段设置默认修饰符的方法。您可以控制字段的访问级别并指定它们是否应该是final。这在基于 Spring 的应用程序中特别有用,您可能希望建立一致的字段级访问控制,而无需为每个字段显式声明它。

@FieldDefaults做什么

当您使用 注释类时@FieldDefaults,您可以指定两个关键元素:

  • 访问级别:字段的可见性,例如PRIVATE、PROTECTED、PACKAGE或PUBLIC。默认值为PRIVATE。

  • Final:一个布尔值,指定字段是否应为final。默认为false.

通过使用此注释,您可以方便地为类中的所有字段设置默认行为,从而促进更清晰、更一致的代码。当与其他 Lombok 注释(例如@Data.

基本用法

这是一个简单的示例,展示了如何使用@FieldDefaults:

import lombok.experimental.FieldDefaults;
import lombok.AccessLevel;

@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true)
public class ImmutablePerson {
    String name;
    int age;
}

在此示例中,我们将所有字段设置为private和final。如果没有@FieldDefaults,您将不得不将每个字段显式声明为private final.

与其他注释结合

您经常可以看到在 Spring 应用程序中@FieldDefaults与 一起使用。@Data虽然@Data提供了丰富的功能,如 getter、setter 和equals()方法hashCode(),@FieldDefaults但确保所有字段都是私有的并且可能是不可变的。这可以创建一个既简洁又安全的健壮模型类。

import lombok.Data;
import lombok.experimental.FieldDefaults;
import lombok.AccessLevel;

@Data
@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true)
public class SecureBook {
    String title;
    String author;
    int pages;
}

在这个修改后的Book类示例中,我们不仅拥有 提供的所有功能@Data,而且还确保所有字段都是private和final,从而增强了类的不变性和封装性。

makeFinal关于属性的注释

makeFinal = true当您创建不可变类时,设置效果很好,但它确实限制了其他 Lombok 注释(例如@Setter. 在用 注释的类中@Data,该makeFinal = true设置实际上会禁用 setter 方法的生成,因为final字段一旦初始化就无法修改。

@FieldDefaults因此,与 结合使用时@Data,必须考虑不变性是否比更改字段值的能力更重要。

该@FieldDefaults注释提供了一种为 Java 类建立默认字段级设置的优雅方法。虽然注释看起来很简单,但它对代码可读性和可维护性的影响可能很大。当明智地使用时,特别是与其他 Lombok 注释(如 )结合使用@Data,@FieldDefaults可以帮助您创建更干净、更高效的代码,行数更少,一致性更好。

何时使用和何时不使用

决定何时使用 Lombok的@Data和@FieldDefaults注释并不是一个非黑即白的决定。虽然这些注释提供了许多优点,例如更干净且更易于维护的代码,但它们也有自己的一系列考虑因素。下面,我们将详细介绍一些使用这些注释会有所帮助的场景,以及一些您可能需要谨慎操作的场景。

何时使用@Data以及@FieldDefaults

  1. 快速原型制作:当您需要快速开发原型或概念证明时,这些注释可以显着加快您的编码速度。

  2. POJO/数据类:当您有主要用于保存数据的简单类,并且您确定需要@Data生成的所有方法时,使用此注释是理所当然的。

  3. Spring Boot 应用程序:对于通常重视约定而非配置的 Spring Boot 应用程序,使用@Data并@FieldDefaults符合框架减少样板代码的理念。

  4. 短期项目:在生命周期较短的项目中,可维护性不是一个大问题,使用这些注释可以使开发过程更加高效。

  5. 团队一致性:如果团队中的每个人都熟悉Lombok及其注释,那么使用@Data和@FieldDefaults可以使代码更加统一,更容易理解。

何时不使用@Data以及@FieldDefaults

  1. 复杂的业务逻辑:对于具有复杂业务逻辑的类,使用@Data可能很危险,因为它会生成可能绕过您的逻辑的设置器。在这些场景中,手动编写方法可以为您提供更好的控制。

  2. 不可变性:如果您的应用程序需要不可变对象,请小心,@Data因为它默认生成 setter。您仍然可以使用@FieldDefaults(makeFinal = true)将字段设为最终字段,但这将使@Data注释的设置器生成功能变得毫无意义。

  3. 技能水平各异的大型团队:在并非每个人都熟悉 Lombok 的团队中,使用这些注释可能会引入学习曲线,并使代码库对于新手来说更难理解。

  4. 库开发:如果您正在开发供公共或广泛内部使用的库,则使用 Lombok 注释可能会强制用户产生依赖性或意外行为。

  5. 性能关键代码:在性能至关重要的场景中,自动生成的方法可能不如手动编写的方法优化,特别是对于equals()大型hashCode()对象等操作。

  6. 继承和多态性: 在扩展类或实现具有自己的接口和实现时,@Data生成equals()的hashCode()方法可能不遵守所需的约定。在这种情况下,建议手动编写这些方法。equals()hashCode()

虽然@Data和@FieldDefaults可以显着减少样板代码并使代码更清晰,但应仔细考虑它们的使用。它们是简化开发的优秀工具,但并不是适用于所有情况的灵丹妙药。知道何时使用这些注释(也许更重要的是,何时不使用它们)对于维护平衡、高效和易于理解的代码库至关重要。

结论

Lombok 项目@FieldDefaults和@Data注释可以显着减少 Spring 应用程序中的样板代码,使代码更具可读性和可维护性。然而,人们应该谨慎对待何时何地使用这些注释。它们对于简单数据类非常有益,但可能不适合包含复杂行为或需要自定义方法(如equals()、hashCode()、 或 )实现的类toString()。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

missterzy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值