[英]Lombok @Builder with inheritance that requires a certain field
Java 11, Spring Boot and Lombok here. Java 11, Spring 在这里启动和龙目岛。 I am trying to build up a hierarchy of objects extending Spring's
ApplicationEvent
class which forces me to provide a constructor:我正在尝试建立扩展 Spring 的
ApplicationEvent
class 的对象层次结构,这迫使我提供一个构造函数:
public ApplicationEvent(Object source) {
...
}
So extending ApplicationEvent
I have a TrackedEvent
that is an abstract base class for my other events to build off:因此,扩展
ApplicationEvent
我有一个TrackedEvent
,它是一个抽象基础 class ,用于构建我的其他事件:
public abstract class TrackedEvent extends ApplicationEvent {
private String correlationId;
private String description;
// ... lots of fields here
}
One of the (many) events extending TrackedEvent
is OperationalEvent
:扩展
TrackedEvent
的(许多)事件之一是OperationalEvent
:
public class OperationalEvent extends TrackedEvent {
private OperationType type;
private OperationStatus status;
// ... several more fields here
}
Other than the source: Object
field, which is required by the grandparent ApplicationEvent
constructor, all other TrackedEvent
and OperationalEvent
fields are optional.除了
source: Object
字段,这是祖父ApplicationEvent
构造函数所必需的,所有其他TrackedEvent
和OperationalEvent
字段都是可选的。 So because there are so many fields here to populate and instantiation-time, I feel the Builder Pattern is appropriate.所以因为这里有很多字段要填充和实例化时间,我觉得构建器模式是合适的。 So I'd like to employ Lombok's
@Builder
annotation (and possibly other annos) to obtain an API something like so:因此,我想使用 Lombok 的
@Builder
注释(可能还有其他注释)来获得 API 类似这样的东西:
OperationalEvent opsEvent = OperationalEvent.Builder(this)
.description("something happened")
.status(OperationalStatus.THE_THING)
.build();
My thinking here is we would pass this
in as a required builder constructor argument (to satisfy ApplicationEvent
's constructor for source: Object
...somehow) and then use the @Builder
like normal.我的想法是我们将
this
作为必需的构建器构造函数参数传递(以满足ApplicationEvent
的source: Object
...不知何故),然后像平常一样使用@Builder
。
Is this possible to do in Lombok, and if so, how?在龙目岛可以做到这一点,如果可以,怎么做?
As a fallback I can just write my own builders but since I have so many subclasses it would be great to leverage Lombok if at all possible.作为后备,我可以只编写自己的构建器,但由于我有这么多子类,如果可能的话,利用 Lombok 会很棒。
Since you can't use @SuperBuilder
annotation, beacause you don't have access to ApplicationEvent
class, as far as I can see, the only solution is to do something like following:由于您不能使用
@SuperBuilder
注释,因为您无权访问ApplicationEvent
class,据我所知,唯一的解决方案是执行以下操作:
Assume that you have TrackedEvent
class wich looks something like this:假设您有
TrackedEvent
class 看起来像这样:
public class TrackedEvent extends ApplicationEvent {
protected String correlationId;
protected String description;
public TrackedEvent(Object source, String correlationId, String description) {
super(source);
this.correlationId = correlationId;
this.description = description;
}
public TrackedEvent(Object source) {
super(source);
}
}
And you have OperationalEvent
class wich extends above class.你有
OperationalEvent
class 延伸到 class 之上。 Than, you can implement builder pattern in OptionalEvent class like this:然后,您可以像这样在 OptionalEvent class 中实现构建器模式:
public class OperationalEvent extends TrackedEvent {
private String type;
private String status;
public OperationalEvent(Object source) {
super(source);
}
@Builder(builderMethodName = "optionalEvent")
public OperationalEvent(Object source, String correlationId, String description, String type, String status) {
super(source, correlationId, description);
this.type = type;
this.status = status;
}
@Override
public String toString() {
return "OperationalEvent{" +
"type='" + type + '\'' +
", status='" + status + '\'' +
"correlationId:" + correlationId +
'}';
}
}
And than the following code should work as expected:并且以下代码应该按预期工作:
public static void main(String[] args) {
ApplicationEvent applicationEvent = new ApplicationEvent(new Object()) {
@Override
public Object getSource() {
return super.getSource();
}
};
OperationalEvent opsEvent = OperationalEvent.optionalEvent()
.description("something happened")
.source(applicationEvent)
.status("status")
.correlationId("1")
.build();
}
You can use @SuperBuilder
together with an intermediate abstract class, as described here .您可以将
@SuperBuilder
与中间抽象 class 一起使用,如此处所述。
The advantage over using customized @Builder
s is that you only have to manually implement this single custom intermediate class once.使用自定义
@Builder
的优势在于您只需手动实现这个单个自定义中间 class 一次。 There is no need for customization in every subclass.不需要在每个子类中进行定制。
In this case, the intermediate class looks as follows:在这种情况下,中间 class 如下所示:
public abstract class ApplicationEventSuperBuilderEnabler extends ApplicationEvent {
public static abstract class ApplicationEventSuperBuilderEnablerBuilder<C extends ApplicationEventSuperBuilderEnabler, B extends ApplicationEventSuperBuilderEnablerBuilder<C, B>> {
private Object source;
public B source(Object source) {
this.source = source;
return self();
}
protected abstract B self();
public abstract C build();
}
protected ApplicationEventSuperBuilderEnabler(ApplicationEventSuperBuilderEnablerBuilder<?, ?> b) {
super(b.source);
}
}
Next, let all your direct subclasses extend ApplicationEventSuperBuilderEnabler
(instead of ApplicationEvent
) and put a @SuperBuilder
on all classes:接下来,让您的所有直接子类扩展
ApplicationEventSuperBuilderEnabler
(而不是ApplicationEvent
)并在所有类上放置一个@SuperBuilder
:
@SuperBuilder
public abstract class TrackedEvent extends ApplicationEventSuperBuilderEnabler { ... }
@SuperBuilder
public class OperationalEvent extends TrackedEvent { ... }
Now you can use it like this:现在你可以像这样使用它:
OperationalEvent opsEvent = OperationalEvent.builder()
.source(this)
.description("something happened")
.status(OperationalStatus.THE_THING)
.build();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.