我问了一个一般的 Spring 问题:Auto-cast SpringBeans并且有很多人回答说ApplicationContext.getBean()应该尽可能避免调用 Spring。这是为什么?
ApplicationContext.getBean()
我还应该如何访问我配置 Spring 来创建的 bean?
我在非 Web 应用程序中使用 Spring,并计划访问LiorH所描述ApplicationContext的共享对象。
ApplicationContext
修正案
我接受下面的答案,但这是 Martin Fowler 的另一种看法,他讨论了依赖注入与使用服务定位器的优点(这与调用 Wrapped 基本相同ApplicationContext.getBean())。
Fowler 部分指出,“ 使用服务定位器,应用程序类通过给定位器的消息显式地请求它[服务]。通过注入没有显式请求,服务出现在应用程序类中 - 因此控制反转。控制反转是框架的一个常见特性,但它是有代价的。它往往难以理解并且在你尝试调试时会导致问题。所以总的来说我更愿意避免它[控制反转] 除非我需要它。这并不是说这是一件坏事,只是我认为它需要证明自己比更直接的选择更合理 。
我在对另一个问题的评论中提到了这一点,但控制反转的整个想法是让 你的任何类都不知道或关心他们如何获取他们所依赖的对象 。这使您可以轻松地随时更改您使用的给定依赖项的实现类型。它还使类易于测试,因为您可以提供依赖项的模拟实现。最后,它使类 更简单 ,更专注于它们的核心职责。
调用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.
myClass
myOtherClass
以这种方式声明所有内容,其根源在于:
<bean id="myApplication" class="MyApplication"> <property name="myCentralClass" ref="myCentralClass"/> <property name="myOtherCentralClass" ref="myOtherCentralClass"/> </bean>
MyApplication是最核心的类,并且至少间接依赖于程序中的所有其他服务。引导时,在您的main方法中,您可以调用applicationContext.getBean("myApplication")但您不需要getBean()在其他任何地方调用!
MyApplication
main
applicationContext.getBean("myApplication")
getBean()