【问题标题】:Why Spring DependsOn annotation cannot use to auto wire an interface为什么 Spring DependsOn 注释不能用于自动连接接口
【发布时间】:2017-09-18 22:37:28
【问题描述】:

当我正在编写一些 spring 代码时,我正在使用带有 class 和 annotation-config 的 spring 4。我已经声明了一个 bean 实现了一个接口作为一个组件。而且我正在尝试使另一个 bean 依赖于它的接口时间。但它不起作用,因为 spring 抛出一个错误,在该名称中找不到 bean。我认为这可能是因为取决于仅适用于具体类自动线,但我不知道为什么它以这种方式设置?有谁可以解释为什么依赖注释不允许类型自动连接到接口?

简单的示例代码是这样的

@Component
class A implement B{
}

@Component
@DependsOn("B")
class C {
}

上面的代码不能工作,除非我改变 @DependsOn("B")@DependsOn("A")

【问题讨论】:

  • 据我所知,@DependsOn 不会自动装配任何东西。你能澄清一下你想要做什么吗?
  • 因为DependsOn 作用于名称而不作用于类型。
  • 感谢您的所有帮助。在做了一些搜索之后,我发现,dependsOn 只适用于类。当使用dependsOn时,我们需要给代码一个classId,因为Spring必须实例化那个类。
  • @M.Deinum - DependsOn 也适用于类名 - 它只是不适用于接口。当您将它与 bean 配置一起使用时,您可以将它与 bean 名称一起使用。当您使用它注释组件时,您可以将它与类名一起使用。当有 20 个网站互相复制彼此的示例时,这就是我们遇到的问题 - 当您重新阅读所有副本时,您开始相信这是做某事的唯一方法。
  • @DependsOn 不适用于类名,它仅适用于豆类名称。 Spring 中的默认设置是将类名转换为 beanname(请检查默认的 BeanNameGenerator 实现)。它使用简单的类名而不是 FQN。

标签: java spring


【解决方案1】:

对于简单的自动装配,在字段或构造函数上使用@Autowired。从 Spring 4.3 开始,您可以在使用构造函数注入时省略 @Autowired

@Component
class A implement B {
}

@Component
class C {
    private final B b;

    public C(B b) {
        this.b = b;
    }
}

【讨论】:

    【解决方案2】:

    一般来说,永远不要使用DependsOn如果你需要它,你可能做错了什么,或者你有一个极端的极端情况。我从 2006 年开始使用 Spring,现在还不需要它。

    JavaDoc 说

    在 bean 的情况下很少使用 不通过属性或构造函数参数显式依赖另一个, 而是取决于另一个 bean 初始化的副作用。

    这基本上意味着你只使用DependsOn 如果你或其他人编写了错误的代码。例如,一个 bean 构造函数在磁盘上创建另一个 bean 在构造时需要的资源。 Springs IoC 容器和声明式连接允许您控制 bean 之间的依赖关系,但在极少数情况下,某些遗留代码具有未声明的依赖关系DependsOn 允许您控制不相关的 spring bean 的构造顺序。

    【讨论】:

    • 遗留代码并不是需要 DependsOn 的良好 Spring 代码的唯一示例。考虑一个使用 jersey ioc 和 spring 的 http 服务组件。如果您不希望您的应用程序在某个数据采集组件完成其初始化和数据收集过程之前“营业”,那么您可以在您的 http 服务组件上使用 DependsOn 来指示它依赖于该数据采集组件。没有直接的spring依赖,但是你仍然需要服务器在数据准备好之后才能启动。
    • @John Calcote 这个案例被SmartInitializingSingleton接口stackoverflow.com/a/48771885/355438覆盖
    • 相当迂腐的答案。当然,有些用例需要使用此注解,否则将无法使用。想到的一个例子是一个依赖于可用外部服务器的 bean,但您可能希望在(黄瓜)测试期间模拟/存根。在这种情况下,服务器不可用,因为您在测试期间启动了它(例如:嵌入式 DB、JMS、FTP、MailServer 等)
    • @BennyBottema 我为几个基于 Spring 的大型项目构建了 Spring 测试基础设施,但我仍然没有使用 DependsOn。如果您依赖外部资源,例如 testcontainers JdbcDatabaseContainer,我更喜欢将它们链接到 Spring bean,因此依赖关系是显式的。如果我需要填充外部资源,我将使用 SmartLifeCyle bean 来完成,因此 bean 实例化阶段和生命周期开始有明确的分离,您可以在其中与资源交互并启动后台线程。
    【解决方案3】:

    我在尝试使用depends时遇到了同样的问题,但经过研究,我发现最好的方法是在类C构造函数中删除B的依赖关系,并在init注解的方法中使用此逻辑@ 987654322@,所以在初始化所有构造函数后,这个方法将被执行。 希望我的回答对你有所帮助。

    【讨论】:

      猜你喜欢
      • 2014-04-06
      • 2018-10-18
      • 2018-03-12
      • 1970-01-01
      • 2011-11-01
      • 2011-04-05
      • 2015-05-27
      • 1970-01-01
      • 2010-09-13
      相关资源
      最近更新 更多