上下文
使用Spring 4.1.7的应用程序。所有配置都是XML文件(不使用注释),我宁愿保持这种方式(但如果必须,我可以改变完成的方式)。
问题
我创建了一个带有构建器类的新类。
现在我想将其他bean注入这个新类。我可以使用查找方法和类似的解决方案来执行此操作,然后在调用方bean中使用新类的构建器来创建实例。但是,我宁愿将这个新类的实例注入其调用者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”实例注入“Processor”类。但要做到这一点,处理器必须是一个bean或者我必须使用像查找方法这样的东西。另一方面,无论我想在哪里使用处理器,我都必须做这样的事情:
new Processor.Builder()
.withTimeOut(1000L)
.withNewStatus(StatusEnum.UPDATED)
.build()
.updateDatabase();
而不是这个,我想知道我是否可以使处理器成为Spring可以为其调用者注入的bean,同时保持其不变性。然后可以通过Spring将DaoBean的实例注入到Processor中。这样我就能够分离布线代码和业务逻辑。
值得一提的是,Builder有超过2个字段,并非所有字段都必须设置。这就是为什么我认为抽象工厂是可行的方法(以不同的方式构建处理器的实例)。
答案 0 :(得分:0)
在保留构建器的同时,一个解决方案可能只是简单地使Builder本身成为一个Spring bean ......
这允许这样的东西......
@Autowired
private Builder builder;
public void someMethod() {
Result = builder.withX(...).doSomething();
}
这样,您的Result对象是不可变的,可以通过一个漂亮的构建器创建,构建器可以将Spring bean(在您的情况下为dao)注入其中,而没有人注意到它在那里。
唯一改变的是,你自己不创建构建器,但让Spring为你创建它......
@Component
@Scope("prototype") // normally a good idea
public static class Builder {
@Autowired
private DaoBean dao;
// your logic here
}
(与JavaConfig或XML配置相同,如果您不想扫描。)
特别是对于许多组合,我更喜欢构建器模式,因为工厂需要复杂的方法签名。当然,构建器的缺点是,如果给定的属性类型组合至少在理论上是可接受的,则无法在编译时进行检查。好的,您可以使用各种构建器来模拟它,但这可能是过度的。