问题描述
我问了一个普通的Spring问题:并让多人回复应尽可能避免调用Spring的 ApplicationContext.getBean()
。这是为什么?
I asked a general Spring question: Auto-cast Spring Beans and had multiple people respond that calling Spring's ApplicationContext.getBean()
should be avoided as much as possible. Why is that?
我还应该如何获得我配置Spring创建的bean的权限?
How else should I gain access to the beans I configured Spring to create?
我正在使用Spring在非Web应用程序中,并计划访问共享 ApplicationContext
对象。
I'm using Spring in a non-web application and had planned on accessing a shared ApplicationContext
object as described by LiorH.
修正案
我接受下面的答案,但这是Martin Fowler的另一个选择,(与调用包装的 ApplicationContext.getBean()
基本相同。)
I accept the answer below, but here's an alternate take by Martin Fowler who discusses the merits of Dependency Injection vs. using a Service Locator (which is essentially the same as calling a wrapped ApplicationContext.getBean()
).
部分地,Fowler声明,使用服务定位器,应用程序类通过向定位器的消息显式地请求它[服务]。注入时没有明确的请求,服务出现在t他的应用类 - 因此控制反转。
控制反转是框架的一个共同特征,但它是有代价的。当您尝试调试时,它往往很难理解并导致问题。所以总的来说,我宁愿避免它[控制反转],除非我需要它。这并不是说这是一件坏事,只是因为我认为它需要通过更简单的替代方案来证明自己的合理性。
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."
推荐答案
我在对另一个问题的评论中提到了这一点,但是控制反转的整个想法是让没有一个类知道或关心他们如何获得他们依赖的对象这使得您可以随时轻松更改您使用的给定依赖项的实现类型。它还使类易于测试,因为您可以提供依赖项的模拟实现。最后,它使类更简单更关注他们的核心责任。
I mentioned this in a comment on the other question, but the whole idea of Inversion of Control is to have none of your classes know or care how they get the objects they depend on. This makes it easy to change what type of implementation of a given dependency you use at any time. It also makes the classes easy to test, as you can provide mock implementations of dependencies. Finally, it makes the classes simpler and more focused on their core responsibility.
调用 ApplicationContext.getBean()
不是控制反转虽然更改为给定bean名称配置的实现仍然很容易,但是现在该类直接依赖于Spring来提供该依赖,并且无法以其他任何方式获取它。您不能只创建自己的模拟实现参加一个测试课程并自己传递给它。这基本上违背了Spring作为依赖注入容器的目的。
Calling ApplicationContext.getBean()
is not Inversion of Control! While it's still easy to change what implemenation is configured for the given bean name, the class now relies directly on Spring to provide that dependency and can't get it any other way. You can't just make your own mock implementation in a test class and pass that to it yourself. This basically defeats Spring's purpose as a dependency injection container.
你想说的每个地方:
MyClass myClass = applicationContext.getBean("myClass");
您应该例如声明一个方法:
you should instead, for example, declare a method:
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
。
Spring will then automatically inject myClass
into myOtherClass
.
以这种方式声明所有内容,并在其根部都有类似的内容:
Declare everything in this way, and at the root of it all have something like:
<bean id="myApplication" class="MyApplication">
<property name="myCentralClass" ref="myCentralClass"/>
<property name="myOtherCentralClass" ref="myOtherCentralClass"/>
</bean>
MyApplication
是最核心的类,至少间接地取决于您的程序中的每个其他服务。引导时,在 main
方法中,您可以调用 applicationContext.getBean(myApplication)
,但您不需要在其他任何地方拨打 getBean()
!
MyApplication
is the most central class, and depends at least indirectly on every other service in your program. When bootstrapping, in your main
method, you can call applicationContext.getBean("myApplication")
but you should not need to call getBean()
anywhere else!
这篇关于为什么Spring的ApplicationContext.getBean被认为是坏的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!