我们有一个基于 Spring 的大型应用程序,其中包括不同的模块以及自定义 API。虽然有些模块需要 Spring 上下文,因为它们只是包装了领域模型的一部分,但我们认为我们的一些 API 不需要。
例如,我们围绕 Jackson / Jersey 编写了一个包装器来提供和使用 REST 服务。有一个中央接口可以访问此 API。然而,实现需要另一个类和另一个类,依此类推。所以一个简单的初始化将是
A a = new A(new B(new C(), new D(new E())))
我们目前免于使用@Inject
. 此 API 的上下文会扫描包,然后将其导入目标应用程序。
<import resource="classpath:api-context.xml" />
我们对此感到不舒服,并希望将 spring 上下文踢出 REST 包装器,这意味着我们希望 API 不需要,但不知道如何去做。它应该表示以下两种之一:
构造函数参数
在目标上下文中,这将需要创建几个 bean,每个 bean 都使用其依赖项进行初始化
<bean id="a" class="...A">
<constructor-arg>
<ref = b " />
</constructor-arg>
</bean>
<bean id="b" class="...B">
<constructor-arg>
<ref = c " />
</constructor-arg>
</bean>
<!-- And so on -->
Getter 和 Setter
或者,假设这A
是AInterface
AInterface 的特定实现,我们可以说,A 默认使用 BInterface 的某个实现,依此类推,实际上在内部使用 new 设置它们:
public class A implements AInterface {
private BInterface b = new B();
public getB() {return b;}
public setB(B b) {this.b = b) }
}
// and so on
然后在我的目标上下文中,如果我想使用默认配置,我可以用一行初始化中央访问
<bean id="a" class="...A" />
或使用属性来设置它的 B。但是,如果我想在更远的地方更改一些东西,我必须初始化所有 bean 并设置属性。
如果我将 new 用于测试之外的服务,它对我来说似乎也不干净。
所以我们想知道其他 API 开发人员如何在不依赖上下文导入的情况下使他们的接口和 bean 可访问(顺便说一句,这也会用许多可能不需要的 bean 混淆目标上下文,例如,如果一个 API 提供了多个服务,而我只想要使用一个)?
编辑
不确定这是否更好:
public class A implements AInterface {
private BInterface b
public A() {
b = new B();
}
public getB() {return b;}
public setB(B b) {this.b = b) }
}
或者
public class A implements AInterface {
private BInterface b
public A(B b) {
this.b = b;
}
}
从测试的角度来看,后者感觉最好,但它让我们回到了我上面描述的链,在我可以初始化 A 之前,我必须在我的上下文中初始化所有依赖的 bean。这感觉像太多的配置开销。
有人可能会争辩说,在使用类之前需要初始化所有依赖项是很正常的,我们应该重构我们的代码。然而,我们最终会得到很多实用程序/帮助程序类,它们也不是最好的设计,因为它们很难替换或测试。