小编典典

为什么 Spring 的 ApplicationContext.getBean 被认为不好?

all

我问了一个一般的 Spring 问题:Auto-cast SpringBeans并且有很多人回答说ApplicationContext.getBean()应该尽可能避免调用 Spring。这是为什么?

我还应该如何访问我配置 Spring 来创建的 bean?

我在非 Web 应用程序中使用 Spring,并计划访问LiorH所描述ApplicationContext的共享对象。

修正案

我接受下面的答案,但这是 Martin Fowler
的另一种看法,他讨论了依赖注入与使用服务定位器的优点(这与调用
Wrapped 基本相同ApplicationContext.getBean())。

Fowler 部分指出,“ 使用服务定位器,应用程序类通过给定位器的消息显式地请求它[服务]。通过注入没有显式请求,服务出现在应用程序类中 -
因此控制反转。控制反转是框架的一个常见特性,但它是有代价的。它往往难以理解并且在你尝试调试时会导致问题。所以总的来说我更愿意避免它[控制反转]
除非我需要它。这并不是说这是一件坏事,只是我认为它需要证明自己比更直接的选择更合理


阅读 87

收藏
2022-04-22

共1个答案

小编典典

我在对另一个问题的评论中提到了这一点,但控制反转的整个想法是让 你的任何类都不知道或关心他们如何获取他们所依赖的对象
。这使您可以轻松地随时更改您使用的给定依赖项的实现类型。它还使类易于测试,因为您可以提供依赖项的模拟实现。最后,它使类 更简单
,更专注于它们的核心职责。

调用ApplicationContext.getBean()不是控制反转!虽然更改为给定 bean 名称配置的实现仍然很容易,但该类现在直接依赖
Spring 来提供该依赖关系,并且无法以任何其他方式获得它。您不能只是在测试类中制作自己的模拟实现并自己将其传递给它。这基本上违背了 Spring
作为依赖注入容器的目的。

你想说的每一个地方:

MyClass myClass = applicationContext.getBean("myClass");

例如,您应该声明一个方法:

public void setMyClass(MyClass myClass) {
   this.myClass = myClass;
}

然后在您的配置中:

<bean id="myClass" class="MyClass">...</bean>

<bean id="myOtherClass" class="MyOtherClass">
   <property name="myClass" ref="myClass"/>
</bean>

然后 Spring 会自动myClass注入myOtherClass.

以这种方式声明所有内容,其根源在于:

<bean id="myApplication" class="MyApplication">
   <property name="myCentralClass" ref="myCentralClass"/>
   <property name="myOtherCentralClass" ref="myOtherCentralClass"/>
</bean>

MyApplication是最核心的类,并且至少间接依赖于程序中的所有其他服务。引导时,在您的main方法中,您可以调用applicationContext.getBean("myApplication")但您不需要getBean()在其他任何地方调用!

2022-04-22