为什么 Spring 的 ApplicationContext.getBean 被认为不好? [英] Why is Spring's ApplicationContext.getBean considered bad?

查看:38
本文介绍了为什么 Spring 的 ApplicationContext.getBean 被认为不好?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我问了一个普遍的 Spring 问题:Auto-cast Spring Beans 并且有很多人回答应尽可能避免调用 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?

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

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 指出,使用服务定位器,应用程序类通过给定位器的消息显式地请求它 [服务].通过注入,没有显式请求,服务出现在应用程序类中 -因此控制反转.控制反转是框架的一个共同特征,但它是有代价的.当您尝试调试时,它往往难以理解并导致问题.所以总的来说,除非我需要它,否则我更愿意避免它[控制反转].这并不是说这是件坏事,只是我认为它需要通过更直接的替代方案来证明自己的合理性."

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 被认为不好?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆