【问题标题】:Spring Boot AutoConfiguration OrderSpring Boot 自动配置顺序
【发布时间】:2015-02-24 09:05:39
【问题描述】:

在多模块 Maven 项目中使用 Spring Boot 按所需顺序应用一些 Spring 配置时我遇到了一些麻烦。

我有我自己编写的模块 A 和 B 以及对第三方模块的依赖,我在模块 C 中无法控制(依赖如下:A 依赖于 C,B 依赖于 A)

在模块 A 中,我有一个用 @Configuration@AutoConfigureBefore(ClassFromModuleD.class) 注释的类。在模块 B 中,我有另一个用 @Configuration@AutoConfigureBefore(ClassFromModuleA.class) 注释的类

我希望这会导致我的模块 B 中的 bean 定义首先被配置,然后是我的模块 A 配置类中的 bean,最后是 C 中的那些。

我还尝试向模块 A 和 B 添加一个 META-INF/spring.factories 文件,该文件声明了它自己的模块中存在的单个配置文件。例如。对于模块 A

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.exmaple.moduleAConfiguration

在模块 B 中:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.exmaple.moduleBConfiguration

我没有看到想要的配置顺序,事实上,它似乎与我想要的完全相反。我已经使用了日志语句和调试器来单步执行,似乎首先应用了模块 C 中的配置,然后是 A,最后是 B。

谁能指出我可能遗漏了什么,或者是否有其他方法可以做到这一点?非常感谢。

【问题讨论】:

  • 你能展示你的主要配置类吗?你所说的“配置”是什么意思(你怎么知道在 euntime 一件事先于另一件事)?
  • 主配置类如下所示:@EnableReactor @SpringBootApplication public class SpringConfiguration { } 我相信顺序不是我想要的,因为我在各种 bean 定义方法中放置了断点并且它们没有被命中我希望的顺序。问题是,模块 C 中的 bean 尝试在尚不存在的上下文中查找 bean,因为它是由尚未自动配置的模块 A 和 B 配置的......如果我逐步执行代码运行模块 C,然后一段时间后配置 bean(为时已晚)!
  • AutoconfigureBefore/After 注释仅适用于将类导入 bean 工厂的顺序。他们没有说明创建 bean 的顺序,因此您的断点并不能真正帮助理解问题。如果无法创建 bean,则肯定有错误和堆栈跟踪,所以发布这些可能会有所帮助?
  • 为什么模块 C 中的 bean 在上下文中“查找”一个 bean(我假设这意味着调用 getBean)而不是让容器自动连接该 bean。后者还将确保在模块 C 中的 bean 之前创建所需的 bean。

标签: spring-boot


【解决方案1】:

Spring AutoConfiguration 用于在某些类是否在类路径中时提供基本配置。

这用于例如如果 Hibernate 在类路径上,则提供基本的 Jpa 配置。

如果要配置spring实例化bean的顺序可以使用

@DependsOn("A") 
public class B{
...    
}

这将创建 bean“A”,而不是“B”。

但是,您想要的顺序可能无法实现。 你写道:

A 依赖于 C,B 依赖于 A

如果“取决于”意味着:A 需要 C 被实例化, bean 必须按以下顺序创建:

  1. C - 因为 C 不依赖任何东西
  2. A - 因为 A 依赖于已经创建的 C。
  3. B - 因为 B 依赖于已创建的 A。

Spring 通过分析 bean 类自动检测依赖关系。

如果 A 有一个自动装配的属性或 C 类型的构造函数参数,spring“知道”它必须在 A 之前实例化 C。

在大多数情况下,这很有效。

在某些情况下,spring 无法“猜测”依赖关系并以不需要的顺序创建 bean。 您可以通过 @DependsOn 注释“通知”spring 关于依赖项。 Spring 将尝试相应地更改顺序。

在您的情况下,如果您描述的依赖项对 spring 不可见,并且创建 bean 不需要依赖项,您可以尝试使用 @DependsOn 更改顺序:

A 依赖于 C,B 依赖于 A

可以实现

@DependsOn("C") 
public class A{
   ...    
}

@DependsOn("A") 
public class B{
   ...    
}

// C comes from another module
// and no need to annotate

【讨论】:

    猜你喜欢
    • 2017-01-23
    • 2017-11-03
    • 2017-01-19
    • 2018-09-09
    • 2018-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多