spring 启动自动配置。意想不到的行为

spring boot auto configuration. unexpected behaviour

我正在尝试使用 spring 启动自动配置功能,但遇到了问题。 我创建了一个 github 存储库以便能够轻松重现“问题”:

git clone https://github.com/clembo590/issues.git --branch spring_boot_auto_configuration

只需 运行 mvn clean install,您将获得我在描述中提到的所有日志。

我已经“启用”了 debug=true spring 启动 属性 以查看哪个 'autoconfiguration' 被激活或未激活(如果它没有激活,为什么它没有活跃)。

我还添加了一些日志来“记录所有已添加到 spring 引导上下文的 bean”。

这是我的自动配置 class。


@Configuration
@ComponentScan(basePackageClasses = MyClass.class)
@ConditionalOnBean(ObjectMapper.class)
@AutoConfigureOrder(Ordered.LOWEST_PRECEDENCE)
public class CleaningAutoConfiguration {

    @Bean
    public Fake fake(){
        return new Fake();
    }

    private static class Fake{

    }

}

第一个奇怪的事情是这个日志:

   CleaningAutoConfiguration:
      Did not match:
         - @ConditionalOnBean (types: com.fasterxml.jackson.databind.ObjectMapper; SearchStrategy: all) did not find any beans of type com.fasterxml.jackson.databind.ObjectMapper (OnBeanCondition)
      Matched:
         - @ConditionalOnBean (types: com.fasterxml.jackson.databind.ObjectMapper; SearchStrategy: all) found bean 'jacksonObjectMapper' (OnBeanCondition)

第一个问题: 为什么@ConditionalOnBean 既匹配又不匹配? (我对这种情况的期望是它应该匹配或不匹配......但不能同时匹配......见问题5)

现在,如果我们查看日志,似乎 CleaningAutoConfigurationNegative matches: 部分。

第二个问题: 为什么 CleaningAutoConfiguration 本身注册为一个 bean ? (我原以为它不会像 Negative matches 部分那样)。

第三个问题: 为什么 fake 仍然注册为 bean(我原以为 fake 不会被注册,甚至没有实例化...)

第四题: 为什么 MyClass 没有注册为 bean?

现在,如果您删除 @ComponentScan(basePackageClasses = MyClass.class),那么随着 CleaningAutoConfiguration 进入 Positive matches 部分,所有这些问题都会消失,但会创建一个新问题:

第五题: 为什么删除 @ComponentScan 会将 CleaningAutoConfiguration 带入 Positive matches 部分? (也许问题 5 与问题 1 有某种联系....?)

问题的根本原因是在 auto-configuration class 上使用了 @ComponentScan,即 not supported:

Furthermore, auto-configuration classes should not enable component scanning to find additional components. Specific @Imports should be used instead.

回答您的具体问题:

Why is @ConditionalOnBean BOTH matching and not matching

它首先作为考虑不受支持的 @ComponentScan 注释的一部分进行评估。这个时候ObjectMapper这个bean还没有定义所以不匹配。随后在 ObjectMapper bean 被定义后对其进行评估,此时它匹配。

why is CleaningAutoConfiguration itself registered as a bean ? (I was expecting it would not as it is in the Negative matches section).

由于正负匹配,报告在这里误导了您。 CleaningAutoConfiguration 由于正匹配是一个 bean。

Why is fake still registered as a bean (I was expecting that fake would not be registered, and not even instanciated...)

报告又误导你了。 CleaningAutoConfiguration 上的条件已匹配,因此其 Fake bean 已定义。

why is MyClass not registered as a bean

CleaningAutoConfiguration 上的条件在考虑 @ComponentScan 注释时不匹配,因此未启用 MyClass 包的组件扫描。

Why removing the @ComponentScan brings CleaningAutoConfiguration into Positive matches section

它可以防止 CleaningAutoConfiguration 的条件在 ObjectMapper bean 尚未定义时被过早评估。当它们最终在预期的时间被评估时,ObjectMapper bean 存在并且条件匹配。