为什么 @ConditionalOnMissingBean 在它应该检查的 bean 之前被调用?

noi*_*ale 5 spring kotlin spring-boot

在我的 Spring Boot 应用程序中,我希望仅在未启用模块时才创建 bean。

在 CoreConfig 中,我定义了两个 bean(geocoder 和 tripDistanceCalculator),并通过@ConditionalOnMissingBean引用这些 bean 应该初始化的接口进行注释。

@Configuration
class CoreConfig {

    private val logger = loggerFor<CoreConfig>()

    @Bean
    @ConditionalOnMissingBean(Geocoder::class)
    fun geocoder(): Geocoder {
        logger.warn("no Geocoder bean instance has been provided. Instantiating default.")

        return object : Geocoder {
            override fun getGeocode(address: String) = Coordinates.Unavailable
        }
    }

    @Bean
    @ConditionalOnMissingBean(TravelDistanceCalculator::class)
    fun travelDistanceCalculator(): TravelDistanceCalculator {
        logger.warn("no TravelDistanceCalculator bean instance has been provided. Instantiating default.")

        return object : TravelDistanceCalculator {
            override fun getTravelDistanceInKm(origin: Coordinates, destination: Coordinates) = Double.NaN
        }
    }

    // other beans definitions...
}
Run Code Online (Sandbox Code Playgroud)

然后 GeolocationConfig 定义了一个实现 Geocoder 和 TravelDistanceCalculator 接口的 bean (HereApiClient)。

@Configuration
@ConditionalOnProperty("app.geolocation.enable")
class GeolocationConfig {

    @Bean
    fun hereApiClient(
        geolocationProperties: GeolocationProperties,
        restTemplate: RestTemplate
    ): HereApiClient =
        HereApiClient(restTemplate, geolocationProperties)

}
Run Code Online (Sandbox Code Playgroud)

app.geolocation.enable定义如trueapplication.yml 中。

这里发生的情况是,在启动时,CoreConfig 中定义的 geocoder 和 TravelDistanceCalculator 默认 bean 也会被初始化,即使 GeolocationConfig 已启用并且 HereApiClient 在它们之后不久也被初始化。

我在这里缺少什么?

Dir*_*yne 3

@ConditionalOn(Missing)Bean旨在用于自动配置类。请参阅 javadoc 如果在通用配置类中使用,则结果取决于首先加载的配置。参见安迪·威尔金森的回答

在您的情况下,您可以轻松地使用相同的属性(您已经提供)来配置正确的bean。

使用@ConditionalOnProperty(name="app.geolocation.enable")GeolocationConfig

使用@ConditionalOnProperty(name="app.geolocation.enable",havingValue="false")上/内CoreConfig

编辑

@ConditionalOnProperty(name="app.geolocation.enable",havingValue="false",matchIfMissing = true)如果您希望CoreConfig在属性丢失时使用 ,请使用。