春季启动自动配置。意外的行为

cle*_*590 2 spring spring-boot spring-autoconfiguration

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

git clone https://github.com/clembo590/issues.git --branch spring_boot_auto_configuration
Run Code Online (Sandbox Code Playgroud)

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

我已经“启用”了debug=truespring boot 属性,以查看哪个“自动配置”已激活或未激活(如果它未激活,为什么它未激活)。

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

这是我的自动配置类。


@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{

    }

}
Run Code Online (Sandbox Code Playgroud)

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

   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)

Run Code Online (Sandbox Code Playgroud)

第一个问题:为什么 @ConditionalOnBean 既匹配又不匹配?(我对这种条件的期望是它应该匹配或不匹配......但不能两者都匹配......参见问题5)

现在,如果我们查看日志,似乎就CleaningAutoConfiguration在该Negative matches:部分中。

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

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

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

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

第五个问题:为什么删除@ComponentScan会CleaningAutoConfiguration进入Positive matchessection?(也许问题 5 与问题 1 有某种联系……?)

And*_*son 5

问题的根本原因是在不支持的@ComponentScan自动配置类上使用:

此外,自动配置类不应启用组件扫描来查找其他组件。@Import应该使用特定的s 来代替。

回答您的具体问题:

为什么@ConditionalOnBean两者匹配而不匹配

首先将其评估为考虑不受支持的@ComponentScan注释的一部分。此时,ObjectMapperbean 尚未定义,因此不匹配。随后在定义 bean 后对其进行评估,ObjectMapper此时它匹配。

为什么 CleaningAutoConfiguration 本身注册为 bean ?(我原以为它不会像负面匹配部分那样)。

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

为什么fake仍然注册为bean(我以为fake不会被注册,甚至没有实例化......)

报道又误导你了。的条件CleaningAutoConfiguration已匹配,因此其Fakebean 已定义。

为什么MyClass没有注册为bean

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

为什么删除“@ComponentScan引入CleaningAutoConfiguration积极匹配”部分

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