Spring 抽象 class 带有 final 字段并继承了 lombok 的 @SuperBuilder

Spring abstract class with final fields and inheritance with lombok's @SuperBuilder

我目前正在尝试使用 lombok 删除一些样板代码,但遇到了一些麻烦。

我有一个抽象class AbstractParent,

@SuperBuilder(toBuilder = true)
@EqualsAndHashCode
@ToString
@Getter
@Setter
public abstract class AbstractParent {
private final field1;
private final field2;

那我有一个ChildClass这样的

@SuperBuilder(toBuilder = true)
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public abstract class Child extends AbstractParent {

而且我还有一些 classes 扩展 Child class

@SuperBuilder(toBuilder = true)
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Component
public abstract class ExtendedChild extends Child {
private final field1;
private final field2;

由于 lombok 不能在构造函数中使用 super,我尝试了 @SuperBuilder 注解而不是手动定义构造函数,但无法启动应用程序。我完全错过了什么吗?这甚至可以用 lombok 和 spring?

错误是:

***************************
APPLICATION FAILED TO START
***************************

Description:

Parameter 0 of constructor in com.fu.extendedChild required a bean of type 'com.fu.extendedChild$extendedChildBuilder' that could not be found.


Action:

Consider defining a bean of type 'com.fu.extendedChild$extendedChildBuilder' in your configuration.

我能够用这段代码重现你的问题

@SuperBuilder(toBuilder = true)
@EqualsAndHashCode
@ToString
@Getter
@Setter
public abstract class AbstractParent {
    private final String field1;
    private final String field2;
}

@SuperBuilder(toBuilder = true)
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
abstract class Child extends AbstractParent {

}

@SuperBuilder(toBuilder = true)
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Component
class ExtendedChild extends Child {
    private final String field1;
    private final String field2;
}

@SuperBuilder 在 class ExtendedChild 上的作用是

protected ExtendedChild(ExtendedChildBuilder<?, ?> b) {
    super(b);
    this.field1 = b.field1;
    this.field2 = b.field2;
}

所以它说你需要一个 ExtendedChildBuilder 实例来构建一个 ExtendedChild 实例。换句话说,您必须在 spring 上下文中有一个构建器才能创建您的对象。

这不是一个好主意,因为构建器是有状态的而不是线程安全的。此外,构建器模式在这里能够在构造对象之前随时提供值。使用构建器作为 Spring bean 否定了这种优势。

如果这是您想要实现的不变性,那么使用具有正确参数的普通旧构造函数会更好(如果正确完成,这不是样板代码,这是一个很好的设计)。 那么,Spring注射就是小儿科了

请不要为了编写更少的代码而牺牲复杂性:)