自定义springboot自动配置无法检测bean

Ale*_*ppa 5 java spring spring-boot

我开发了一个自定义的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
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,似乎条件注释不检测在主@SpringBootApplication注释类中声明的bean .

它仅检测在单独的带@Configuration注释的类中声明的bean .

也就是说,如果我放置两个带@Bean注释的方法,在主类中返回一个LibServer和一个LibClient对象,我最终会在上下文中有两个LibServer和两个LibClient对象(自动配置的对象和显式声明的对象).

本机spring引导自动配置(例如DataSource一个)也可以检测主类中声明的bean(例如带@Bean注释的jdbcTemplate方法).

即使对于在主类中声明的bean,我如何获得正确的bean检测?

编辑

一个完整的多模块maven项目展示了这种行为,请访问https://github.com/AlexFalappa/spring-boot-testcase

Mor*_*fic 7

如果您在application.properties( logging.level.org.springframework=DEBUG) 中设置调试日志级别,您会注意到 Spring 将检测这两个定义。但是,您还将看到发生这种情况的顺序可能不是您所期望的,因为它首先从库配置实例化 bean,然后从您的主类实例化 bean ,因此您会得到 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()
Run Code Online (Sandbox Code Playgroud)

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'
Run Code Online (Sandbox Code Playgroud)

您还可以在AUTO-CONFIGURATION REPORT当前实现中的that 中看到,当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)
...
Run Code Online (Sandbox Code Playgroud)

但是,如果您将相同的条件添加到您的主类,您将看到它将根据 中的定义创建 bean 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)
...
Run Code Online (Sandbox Code Playgroud)


Ste*_*oll 4

您不会自己导入 LibAutoConfiguration,对吗?

这是提示:您的主类位于自动配置类的父包中。所以你实际上是@Configuration通过组件扫描导入你自己的。事实证明,当您处理该类时(通过显式导入而不是通过自动配置),尚未创建任何 bean,因此它确实创建了它们。您的应用程序类稍后会被处理并创建这些 bean。

如果您将定义移到其他地方,它可能会起作用(正如您自己通过 找到的那样LibConfig),但这不是确定性的。

TL;DR确保您的自动配置代码位于单独的空间中,并且不是组件扫描的目标。我已将您的产品DemoLibboApplication移至包装中demo,并且按预期工作。