lombok的@Builder注解原理背后干了啥?

举报
JavaEdge 发表于 2021/06/04 01:46:52 2021/06/04
【摘要】 在Lombok v0.12.0中作为实验功能引入自v1.16.0起获得了 @Singular 支持并被升级到了主要lombok软件包@Builder、@Singular自lombok v1.16.8起,使用可以添加明确的方法@Builder.Default* v1.16.16中添加了功能@Builder(builderMethodName = “”) 从=1.18.8开...
  • 在Lombok v0.12.0中作为实验功能引入
  • 自v1.16.0起获得了 @Singular 支持并被升级到了主要lombok软件包
  • @Builder、@Singular自lombok v1.16.8起,使用可以添加明确的方法
  • @Builder.Default* v1.16.16中添加了功能
  • @Builder(builderMethodName = “”) 从=1.18.8开始是合法的(并且将抑制生成器方法的生成)
  • @Builder(access = AccessLevel.PACKAGE) 从lombok v1.18.8开始是合法的(并将生成具有指定访问级别的构建器类,构建器方法等)

功能

@Builder注解为你的类提供复杂的建造者模式 API。

@Builder 使你可以自动生成使您的类可实例化的代码,例如:

Person.builder()
	.name("AdamSavage")
	.city("SanFrancisco")
	.job("Mythbusters")
	.job("Unchained Reaction")
	.build();

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

使用位置

@Builder可以放在类,构造器或方法上。虽然“基于类”和“基于构造器”模式是最常见的用例,但使用“方法”用例最容易解释。

public class ResponseMessage extends Message<OperationResult> { private ResponseMessage(MessageHeader messageHeader, OperationResult messageBody) { super(messageHeader, messageBody); } public Class getMessageBodyDecodeClass(int opcode) { return OperationType.fromOpCode(opcode).getOperationResultClazz(); } public static ResponseMessage.ResponseMessageBuilder builder() { return new ResponseMessage.ResponseMessageBuilder(); } public ResponseMessage() { } public static class ResponseMessageBuilder { private MessageHeader messageHeader; private OperationResult messageBody; ResponseMessageBuilder() { } public ResponseMessage.ResponseMessageBuilder messageHeader(MessageHeader messageHeader) { this.messageHeader = messageHeader; return this; } public ResponseMessage.ResponseMessageBuilder messageBody(OperationResult messageBody) { this.messageBody = messageBody; return this; } public ResponseMessage build() { return new ResponseMessage(this.messageHeader, this.messageBody); } public String toString() { return "ResponseMessage.ResponseMessageBuilder(messageHeader=" + this.messageHeader + ", messageBody=" + this.messageBody + ")"; } }
}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

被**@Builder**注解的方法(从现在开始称为target)将生成以下7件事:
即构造内部类,在内部类赋值属性,build时调用含有所有属性的构造方法创建对象。

  1. 一个内部静态类,名为FooBuilder,其类型参数与静态方法相同(称为builder)
  2. 在构建器中:目标的每个参数有一个private非static 非 final 字段
  3. 在builder中:包私有的无参数空构造器
  4. 在builder中:对目标的每个参数使用类似 setter 的方法:与该参数具有相同的类型和相同的名称。它返回构建器本身,以便可以将setter调用链接起来
  5. 在builder中:build()调用该方法的方法,并在每个字段中传递。它返回与目标返回相同的类型
  6. 有意义的toString()实现
  7. 在包含target的类中:一个builder()方法,该方法创建builder的新实例

如果该元素已存在,则每个列出的生成元素都将被静默跳过(忽略参数计数并仅查看名称)。这包括构建器本身:如果该类已经存在,则lombok会简单地开始在此现有类中注入字段和方法,除非要注入的字段/方法当然已经存在。但是,您不能在生成器类上放置生成lombok批注的任何其他方法(或构造函数)。例如,您不能放入@EqualsAndHashCodebuilder类。
@Builder可以为收集参数/字段生成所谓的“奇异”方法。它们采用1个元素而不是整个列表,然后将该元素添加到列表中。例如:Person.builder().job(“Mythbusters”).job(“Unchained Reaction”).build();将导致该List jobs字段中包含2个字符串。要获得此行为,必须使用注释字段/参数@Singular。该功能具有其自己的文档。

现在,“方法”模式已经很清楚了,@Builder在构造函数上添加注释的功能类似。实际上,构造函数只是具有特殊语法以调用它们的静态方法:它们的“返回类型”是它们构造的类,并且它们的类型参数与类本身的类型参数相同。

应用于@Builder类就像是将其添加@AllArgsConstructor(access = AccessLevel.PACKAGE)到该类并将@Builder注释应用于此all-args-constructor一样。仅当您自己未编写任何显式构造函数时,此方法才有效。如果确实有显式构造函数,则将@Builder注释放在构造函数上而不是在类上。请注意,如果将@Value和@Builder都放在类上,则@Builder要生成“ wins”的程序包私有构造函数,而禁止@Value要生成的构造函数。

如果@Builder用于生成生成器来生成您自己的类的实例(除非添加@Builder到不返回您自己的类型的方法中,否则通常都是这种情况),您还可以@Builder(toBuilder = true)在类中使用生成实例方法toBuilder();它创建一个新的构建器,该构建器以该实例的所有值开始。您可以将@Builder.ObtainVia注释放在参数(对于构造函数或方法的情况)或字段(对于@Builder类型的情况)上,以指示从该实例获取该字段/参数的值的替代方法。例如,您可以指定要调用的方法:@Builder.ObtainVia(method = “calculateFoo”)。

builder类的名称为FoobarBuilder,其中Foobar是目标的返回类型的简化的,以标题区分大小写的形式-即,@Builderon构造函数和类型的类型名称,以及@Builderon方法的返回类型的名称。。例如,如果@Builder应用于名为的类com.yoyodyne.FancyList,则构建器名称将为FancyListBuilder。如果@Builder将应用于返回的方法,void则将命名构建器VoidBuilder。

构建器的可配置方面包括:

该生成器的类名(默认:返回类型+“生成器”)
该版本()方法的名称(默认:“build”)
该生成器()方法的名称(默认:“builder”)
如果需要toBuilder()(默认值:否)
所有生成的元素的访问级别(默认值:)public。
(不推荐使用)如果您希望构建器的“ set”方法具有前缀,即Person.builder().setName(“Jane”).build()而不是前缀,Person.builder().name(“Jane”).build()则应为前缀。
用法示例,其中所有选项均从其默认值更改:
@Builder(builderClassName = “HelloWorldBuilder”, buildMethodName = “execute”, builderMethodName = “helloWorld”, toBuilder = true, access = AccessLevel.PRIVATE, setterPrefix = “set”)
想要将构建器与JSON / XML工具Jackson一起使用?我们涵盖了:检查@Jacksonized功能。

子类如何使用 @Build 注解?

  • 父类
  • 子类

同时在子类和全参数的构造器使用 @Builder 注解,最终的 build() 函数只返回了空参的构造器创建的一个子类对象,因此属性“采用 builder 方式设置的 字段最终都丢失了。

如果成员被注解,则必须是构造器或方法。如果对类注解,则会生成一个private构造器,并将所有字段作为参数,就像在类上存在 @AllArgsConstructor(AccessLevel.PRIVATE) ,就好像该构造器已经存在而是用@Builder注解。

将其加到类上,相当于包含所有属性的私有构造器,且构造器加上 @Builder 注解。

参考

  • https://projectlombok.org/features/Builder

文章来源: javaedge.blog.csdn.net,作者:JavaEdge.,版权归原作者所有,如需转载,请联系作者。

原文链接:javaedge.blog.csdn.net/article/details/109240946

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。