【问题标题】:Dependency injection in SpringSpring中的依赖注入
【发布时间】:2012-03-16 16:09:11
【问题描述】:

我正在尝试了解依赖注入的工作原理。我正在阅读 Pro Spring 2.5 并已进入第 3 章。我想到的一些问题是:

当您在独立应用程序的 main 方法中创建 bean 工厂(在 Web 应用程序中也很有趣),然后读取 bean 配置文件,然后会发生什么? 它是在此时创建具有依赖关系的 bean 并将它们保存在寄存器中,还是只是它保存在寄存器中的配置信息?

我知道您应该尽量将依赖项查找保持在最低限度,因此如果您有一个 MyApplication 类或引导首选应用程序的东西。现在,如果带有寄存器的工厂仅在 main 方法中可用,那么 Spring 或 POJO 将如何知道在何时何地注入依赖项?寄存器不是只能在main方法中使用吗?既然您不再调用“getBean(...)”了,那么构造发生在哪里?它如何设法将 bean 保持为单例等?

【问题讨论】:

标签: java spring jakarta-ee


【解决方案1】:

我认为最好通过阅读此处发布的链接来回答这个问题:What is dependency injection? 尤其是 Martin Fowler 的文章。

想想你所有的对象都在一个容器里。此容器内的对象的整个生命周期(创建、销毁、初始化)由容器内的 spring 或其他对象管理。那么类构造什么时候发生呢?好吧,当您调用getBean() 时,Spring 将尝试为您获取此类实例。它将具有某些依赖项(spring 管理的属性),因此 spring 也会构造这些类的实例,这些类也将具有其他依赖项,依此类推,直到构建应用程序对象图的相关部分。

当您关闭容器(BeanFactoryApplicationContext,spring 会处理任何必要的关闭(即破坏数据库连接等)。

单例 bean(在应用程序的生命周期内只存在一个实例的 bean)是预先实例化的,但这不是必需的。整个对象图可以按需延迟构建。

在 Web 应用程序中,类似于 getBean() 调用的东西碰巧将某个请求链接到您的控制器,但细节因实现而异。假设这仅发生一次以将每个路由绑定到控制器可能是安全的。

【讨论】:

  • 感谢您清除了某些部分,但是由于您只在起点调用“getBean()”,当其他类从不持有对工厂的引用时,Spring 如何能够注入正确的依赖项等?
  • Spring 调用这些类的构造函数,它们不需要对工厂的引用。
  • 好的,谢谢。我现在已经理解了这个概念,我发现我一开始完全误解了它:)
【解决方案2】:

它是否在此时创建具有依赖关系的 bean 并将它们保存在寄存器中

是的,默认情况下,一旦您创建了 BeanFactoryApplicationContext 的实例(请参阅:BeanFactory vs ApplicationContext),Spring 会创建所有 bean 并将它们连接起来。例外是带有lazyscope 的bean,但如果它们是非惰性bean 的依赖项,尽管如此,它们仍将被创建。

Spring 还管理 bean 初始化的正确顺序。

现在,Spring 或 POJO 将如何知道何时何地注入依赖项

基本上,所有的 bean 都存在于 Spring 容器中。如果您获取一个 bean,它已经具有对其直接依赖项的引用。他们反过来又依赖于其他人。底线是:所有 bean 通常都是在启动时创建并连接起来的,它们是一种单例。

另见

【讨论】:

  • 那么您所说的关于他们如何以及何时获得依赖关系的是 MyApplication 可能依赖于类 A,而后者又依赖于 B 和 C 等等?但是当您使用依赖注入而不是手动查询bean工厂和注册的依赖查找时,我仍然不了解bean注册。每个类如何获取它们的依赖关系?
  • @viper:如何解释这个...一旦你创建了你的应用上下文,所有的 bean 都被创建和连接了。一切都在启动时自动且急切地发生。 Spring将首先创建BC,然后创建A并将BC注入到to中。最后它将创建MyApplication 并注入C。这一切都在启动时完成并保存在内存中。当您向 BeanFactory 询问 MyApplication 实例时,它只会返回已创建的注入依赖项的 bean。调用 getBean() 返回已经存在的,有线 bean。
  • 你晚上有 5 分钟的空闲时间来参加 Java 聊天吗?
  • @Viper,很遗憾没有。但请随时就 SO 提出进一步的问题,我/我们会尽力帮助您
  • 所以这发生在运行时?没有延迟加载,整个应用程序(对象图)在查找 MyApplication 后立即在内存中?它是递归完成的,一次贯穿整个应用程序?也许我开始明白了。如果它在运行时完成,这是否与手动“新建”对象时发生的情况相反?
猜你喜欢
  • 2015-10-04
  • 2012-08-02
  • 1970-01-01
  • 2018-11-21
  • 2012-12-23
  • 1970-01-01
  • 1970-01-01
  • 2011-12-09
相关资源
最近更新 更多