我问了一个常见的Spring问题:自动转换Spring bean,很多人回答说应该尽可能避免调用Spring的ApplicationContext.getBean()。为什么呢?
我还应该如何访问我配置Spring创建的bean呢?
我在一个非web应用程序中使用Spring,并计划访问LiorH所描述的共享ApplicationContext对象。
修正案
我接受下面的答案,但这里有Martin Fowler的另一种观点,他讨论了依赖注入与使用服务定位器(本质上与调用包装的ApplicationContext.getBean()相同)的优点。
In part, Fowler states, "With service locator the application class asks for it [the service] explicitly by a message to the locator. With injection there is no explicit request, the service appears in the application class - hence the inversion of control.
Inversion of control is a common feature of frameworks, but it's something that comes at a price. It tends to be hard to understand and leads to problems when you are trying to debug. So on the whole I prefer to avoid it [Inversion of Control] unless I need it. This isn't to say it's a bad thing, just that I think it needs to justify itself over the more straightforward alternative."
我在另一个问题的评论中提到了这一点,但控制反转的整个思想是让你的任何类都不知道或关心它们如何获得它们所依赖的对象。这使得您可以随时更改所使用的给定依赖项的实现类型。它还使类易于测试,因为您可以提供依赖关系的模拟实现。最后,它使类更简单,更专注于它们的核心职责。
调用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是最核心的类,它至少间接地依赖于程序中的所有其他服务。当引导时,在你的主方法中,你可以调用applicationContext.getBean("myApplication"),但你不需要在其他任何地方调用getBean() !