如何使用 Java 配置覆盖 spring beans

How to override spring beans with Java config

我在尝试覆盖 spring zuul 中定义的 RibbonRoutingFilter bean 时遇到了这个问题。强调一下,我正在做一个覆盖,而不仅仅是创建一个相同类型的 bean。所以一天结束时,我希望 zuul 的 "ribbonRoutingFilter" bean 根本没有注册。

所以我有自己的实现。我尝试的第一件事是使用@component 注释并自动装配依赖项。在构造函数中添加了一个断点,它最终从未被调用。所以我意识到我的定义必须比 zuul 的更早加载。因此,我使用@Configuration 注释和@Order(Ordered.HIGHEST_PRECEDENCE) 创建了一个配置class,并使用@Bean 注释在其中实例化我的class。不过,我的方法总是提前加载。

事实证明,在加载配置 classes 定义时遵循特定顺序 Spring,这就是覆盖发生的地方。 Class org.springframework.context.annotation.ConfigurationClassParser 在方法doProcessConfigurationClass()中有详细的逻辑。我将把我的简化总结或排序规则放在这里:

  1. 如果您的应用程序 class(其中定义了 main() 方法)在其中定义了任何 classes,它们将被解析并首先注册其中的定义
  2. 然后它将注册定义为@component 并定义在@Configuration class
  3. 中的Bean
  4. 然后它将添加由@Import
  5. 引入的定义
  6. 然后它将添加由@ImportResource
  7. 引入的定义
  8. 然后在应用程序中添加来自@bean 方法的定义class
  9. 然后从接口的默认方法(我认为是 java 8)
  10. 然后尝试对任何 parent class 应用程序 class 扩展执行上述相同步骤。

这解释了为什么我的覆盖不起作用。这是因为我一直在尝试在第 2 步中进行尝试。但是 zuul 通过第 3 步中的 @Import 定义了 bean。

所以为了解决我的问题,我在我的应用程序 class 中添加了一个 @Bean 注释方法,并按预期进行了实例化和覆盖。

以上总结可能并不准确,它只是让您了解可能导致覆盖失败的原因。您最好在尝试特定用例时调试 ConfigurationClassParser。