Spring - 使用Builder模式注入(inject)bean

标签 spring dependency-injection builder-pattern

上下文

使用 Spring 4.1.7 的应用程序。所有配置都在 XML 文件中(不使用注释),我宁愿保持这种方式(但如果必须的话,我可以更改完成事情的方式)。

问题

我创建了一个带有构建器类的新类。

现在我想将其他 bean 注入(inject)到这个新类中。我可能可以使用查找方法和类似的解决方案来做到这一点,然后在调用者 bean 中使用新类的构建器来创建一个实例。然而,我宁愿将这个新类的一个实例注入(inject)到其调用者 bean 中,然后通过构建器创建一个实例。这是我不确定如何做到这一点的地方。例如,这对我来说看起来像一个抽象工厂,但我不知道如何在运行时将这些参数(传递给构建器)传递给抽象工厂以及随后它构建的工厂。

一些代码片段可以使问题更清晰:

public final class Processor {

    private final StatusEnum newStatus;
    private final Long timeOut;

    // I'd like this to be be injected by Spring through its setter (below)
    private DaoBean daoInstance;

    private Processor() {
        this.newStatus = null;
        this.timeOut = null;
    }

    private Processor(Builder builder) {
        this.newStatus = builder.getNewStatus();
        this.timeOut = builder.getTimeOut();
    }

    // To be called by Spring
    public void setDaoInstance(DaoBean instance) {
        this.daoInstance = instance;
    }

    public void updateDatabase() {
        daoInstance.update(newStatus, timeOut);
    }

    // Builder class
    public static final class Builder {
        private StatusEnum newStatus;
        private Long timeOut;
        // lots of other fields

        public Long getTimeOut() {
             return this.timeOut;
        }

        public StatusEnum getNewStatus() {
             return this.newStatus;
        }

        public Builder withTimeOut(Long timeOut) {
             this.timeOut = timeOut;
             return this;
        }

        public Builder withNewStatus(StatusEnum newStatus) {
             this.newStatus = newStatus;
             return this;
        }

        public Processor build() {
             return new Processor(this);
        }
    }
}

我希望将“DaoBean”的实例注入(inject)到“Processor”类中。但要做到这一点,处理器必须是一个 bean,否则我必须使用查找方法之类的东西。另一方面,无论我想在哪里使用处理器,我都必须执行以下操作:

new Processor.Builder()
   .withTimeOut(1000L)
   .withNewStatus(StatusEnum.UPDATED)
   .build()
   .updateDatabase();

取而代之的是,我想知道是否可以使 Processor 成为 Spring 可以注入(inject)到其调用者的 bean,同时保持其不变性。然后 Spring 可以将 DaoBean 的实例注入(inject)到 Processor 中。这样我就能够将连接代码和业务逻辑分开。

值得一提的是,Builder 有两个以上的字段,并且并非所有字段都必须设置。这就是为什么我认为抽象工厂是可行的方法(以不同的方式构建处理器的实例)。

最佳答案

一种解决方案,在保留构建器的同时,可能只是简单地使构建器本身成为 Spring bean...

这允许这样的事情..

@Autowired
private Builder builder;

public void someMethod() {
    Result = builder.withX(...).doSomething();
}
这样,您的 Result 对象是不可变的,可以通过一个好的构建器创建,并且构建器可以将 Spring bean(在您的情况下为 dao)注入(inject)其中,而没有人注意到它的存在。

唯一改变的是,您不自己创建构建器,而是让 Spring 为您创建它......

@Component
@Scope("prototype") // normally a good idea
public static class Builder {
    @Autowired
    private DaoBean dao;

    // your logic here
}

(如果您不想扫描,同样适用于 JavaConfig 或 XML 配置。)

特别是对于许多组合,我更喜欢构建器模式,因为工厂需要复杂的方法签名。当然,构建器的缺点是您无法在编译时检查给定的属性类型组合是否至少在理论上是可接受的。好吧,您可以使用各种构建器来模拟这一点,但这可能有点过头了。

关于Spring - 使用Builder模式注入(inject)bean,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39183693/

相关文章:

java - 如何通过读取文件并将其写入另一个文件来为我的类(class)编写单元测试?

c# - 自定义类中的依赖注入(inject) - .NET Core

dependency-injection - angular2 向其他人注入(inject)服务 - 使用@Inject 时出错

java - 我应该如何将 Composite 模式包装到 Builder 模式中?

language-agnostic - 你会在哪里使用构建器模式而不是抽象工厂?

java - 预见从 Spring 4.2 升级到 Spring 5.0.5 时出现的问题

spring - java 9模块从A和B读取包X

java - 在 Java Spring 的 REST 方法中返回后执行清理操作

dependency-injection - 如何使用 StructureMap 注入(inject) AutoMapper IMappingEngine

java - 我可以从构建器那里获得匿名类吗?