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)
现在,如果我们查看日志,似乎 CleaningAutoConfiguration
在 Negative 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 @Import
s 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 存在并且条件匹配。
我正在尝试使用 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)
现在,如果我们查看日志,似乎 CleaningAutoConfiguration
在 Negative 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
@Import
s 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
bringsCleaningAutoConfiguration
into Positive matches section
它可以防止 CleaningAutoConfiguration
的条件在 ObjectMapper
bean 尚未定义时被过早评估。当它们最终在预期的时间被评估时,ObjectMapper
bean 存在并且条件匹配。