[英]Custom springboot autoconfiguration not detecting beans
我开发了一个自定义的Spring Boot自动配置,以便于使用专有的消息库。
主要的自动配置类基本如下:
@Configuration
@ConditionalOnClass({LibServer.class, LibClient.class})
@EnableConfigurationProperties(LibProperties.class)
public class LibAutoConfiguration {
@Autowired
LibProperties props;
@Bean
@ConditionalOnMissingBean(LibServer.class)
public LibServer lbServ() {
// create and configure a server object
}
@Bean
@ConditionalOnMissingBean(LibClient.class)
public LibClient lbClient() {
//create and configure a client object
}
}
但是,条件注释似乎没有检测到主@SpringBootApplication
注释类中声明的bean。
它仅检测在单独的@Configuration
注释的类中声明的bean。
也就是说,如果我放置两个@Bean
注释方法在主类中返回一个LibServer
和一个LibClient
对象,我最终会在LibServer
使用两个LibServer
和两个LibClient
对象(自动配置的对象和显式声明的对象)。
本机spring引导自动配置(例如DataSource
one)也可以检测主类中声明的bean(例如@Bean
注释的jdbcTemplate
方法)。
即使对于在主类中声明的bean,我如何获得正确的bean检测?
编辑
一个完整的多模块maven项目展示了这种行为, 请访问https://github.com/AlexFalappa/spring-boot-testcase
你自己没有导入你的LibAutoConfiguration,对吗?
这是提示:您的主类位于自动配置类的父包中。 所以你实际上是通过组件扫描自己导入@Configuration
。 事实证明,当您处理该类时(通过显式导入而不是通过自动配置),尚未创建任何bean,因此它确实创建了它们。 稍后处理您的应用程序类并创建这些bean。
如果你将定义移到其他地方,它可能会起作用(正如你已经用LibConfig
),但这不是确定性的。
TL;DR
确保您的自动配置代码位于单独的空间中,而不是组件扫描的目标。 我已将DemoLibboApplication
移至demo
包中,并按预期工作。
如果在application.properties
( logging.level.org.springframework=DEBUG
)中设置debug的日志级别,您会注意到Spring将检测这两个定义。 但是您也会看到发生这种情况的顺序可能与您的预期不同 ,因为它首先从库配置实例化bean,从主类实例化AFTERWARDS,因此您获得2个实例(剥离时间戳以使其更友好) :
Bean定义
o.s.b.f.s.DefaultListableBeanFactory : Returning cached instance of singleton bean 'autoConfigurationReport'
a.ConfigurationClassBeanDefinitionReader : Registering bean definition for @Bean method af.spring.boot.libbo.LibAutoConfiguration.lbServ()
o.s.b.f.s.DefaultListableBeanFactory : Returning cached instance of singleton bean 'org.springframework.boot.autoconfigure.condition.BeanTypeRegistry'
o.s.b.f.s.DefaultListableBeanFactory : Returning cached instance of singleton bean 'autoConfigurationReport'
a.ConfigurationClassBeanDefinitionReader : Registering bean definition for @Bean method af.spring.boot.libbo.LibAutoConfiguration.lbClient()
a.ConfigurationClassBeanDefinitionReader : Registering bean definition for @Bean method af.DemoLibboApplication.libServ()
a.ConfigurationClassBeanDefinitionReader : Registering bean definition for @Bean method af.DemoLibboApplication.libClient()
Bean实例化
o.s.b.f.s.DefaultListableBeanFactory : Creating shared instance of singleton bean 'lbServ'
o.s.b.f.s.DefaultListableBeanFactory : Creating instance of bean 'lbServ'
o.s.b.f.s.DefaultListableBeanFactory : Returning cached instance of singleton bean 'libAutoConfiguration'
Autoconfiguring LibServer
o.s.b.f.s.DefaultListableBeanFactory : Eagerly caching bean 'lbServ' to allow for resolving potential circular references
o.s.b.f.s.DefaultListableBeanFactory : Finished creating instance of bean 'lbServ'
o.s.b.f.s.DefaultListableBeanFactory : Creating shared instance of singleton bean 'lbClient'
o.s.b.f.s.DefaultListableBeanFactory : Creating instance of bean 'lbClient'
o.s.b.f.s.DefaultListableBeanFactory : Returning cached instance of singleton bean 'libAutoConfiguration'
Autoconfiguring LibClient
o.s.b.f.s.DefaultListableBeanFactory : Eagerly caching bean 'lbClient' to allow for resolving potential circular references
o.s.b.f.s.DefaultListableBeanFactory : Finished creating instance of bean 'lbClient'
o.s.b.f.s.DefaultListableBeanFactory : Returning cached instance of singleton bean 'lib.CONFIGURATION_PROPERTIES'
o.s.b.f.s.DefaultListableBeanFactory : Returning cached instance of singleton bean 'org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor'
o.s.b.f.s.DefaultListableBeanFactory : Returning cached instance of singleton bean 'org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor.store'
o.s.b.f.s.DefaultListableBeanFactory : Creating shared instance of singleton bean 'libServ'
o.s.b.f.s.DefaultListableBeanFactory : Creating instance of bean 'libServ'
o.s.b.f.s.DefaultListableBeanFactory : Returning cached instance of singleton bean 'demoLibboApplication'
o.s.b.f.s.DefaultListableBeanFactory : Eagerly caching bean 'libServ' to allow for resolving potential circular references
o.s.b.f.s.DefaultListableBeanFactory : Finished creating instance of bean 'libServ'
o.s.b.f.s.DefaultListableBeanFactory : Creating shared instance of singleton bean 'libClient'
o.s.b.f.s.DefaultListableBeanFactory : Creating instance of bean 'libClient'
o.s.b.f.s.DefaultListableBeanFactory : Returning cached instance of singleton bean 'demoLibboApplication'
o.s.b.f.s.DefaultListableBeanFactory : Eagerly caching bean 'libClient' to allow for resolving potential circular references
o.s.b.f.s.DefaultListableBeanFactory : Finished creating instance of bean 'libClient'
您还可以在AUTO-CONFIGURATION REPORT
看到,在当前实现中,当评估LibAutoConfiguration
中的条件时,它们匹配并且通常会创建bean:
Positive matches:
-----------------
...
LibAutoConfiguration#lbClient matched
- @ConditionalOnMissingBean (types: af.libbo.LibClient; SearchStrategy: all) found no beans (OnBeanCondition)
LibAutoConfiguration#lbServ matched
- @ConditionalOnMissingBean (types: af.libbo.LibServer; SearchStrategy: all) found no beans (OnBeanCondition)
...
但是,如果向主类添加相同的条件,您将看到它将根据LibAutoConfiguration
的定义创建bean,并且在尝试为DemoLibboApplication
创建那些时,它实际上将找到先前创建的bean并跳过实例:
Negative matches:
-----------------
...
DemoLibboApplication#libClient did not match
- @ConditionalOnMissingBean (types: af.libbo.LibServer; SearchStrategy: all) found the following [lbServ] (OnBeanCondition)
DemoLibboApplication#libServ did not match
- @ConditionalOnMissingBean (types: af.libbo.LibServer; SearchStrategy: all) found the following [lbServ] (OnBeanCondition)
...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.