gpt4 book ai didi

java - Spring Boot 传递 @Component 依赖与 @ConditionalOnBean

转载 作者:IT老高 更新时间:2023-10-28 13:45:17 26 4
gpt4 key购买 nike

我有一个 Spring Boot 1.5.x 项目,其中一些 @Component 依赖于其他 @Component,并最终沿着依赖链, 一些 @Component 可以使用 @ConditionalOnProperty 完全启用或禁用。

我正在使用 @ConditionalOnBean 来避免实例化 @Component 依赖于其他因缺少 @Component 而没有被实例化的 >属性.

但是,它只适用于直接依赖,不适用于传递依赖,但我不明白为什么。

让我试着用一个简单的例子来解释一下。

考虑 MyServices.kt:

private val logger = KotlinLogging.logger {}

class MyServices

@ConditionalOnProperty("service.a")
@Service
class ServiceA {
init {
logger.info { "A SERVICE" }
}
}

@ConditionalOnBean(ServiceA::class)
@ConditionalOnProperty("service.b")
@Service
class ServiceB(
private val serviceA: ServiceA
) {
init {
logger.info { "B SERVICE depends on $serviceA" }
}
}

@ConditionalOnBean(ServiceB::class)
@ConditionalOnProperty("service.c")
@Service
class ServiceC(
private val serviceB: ServiceB
) {
init {
logger.info { "C Service depends on $serviceB" }
}
}

使用以下application.yml:

service:
a: false
b: true
c: true

然后 Spring 在启动时崩溃,并出现以下情况:

**************************
APPLICATION FAILED TO START
***************************

Description:

Parameter 0 of constructor in org.gotson.transitivebeandependencies.ServiceC required a bean of type 'org.gotson.transitivebeandependencies.ServiceB' that could not be found.


Action:

Consider defining a bean of type 'org.gotson.transitivebeandependencies.ServiceB' in your configuration.

这是自动配置的结果:

Positive matches:

ServiceC matched:
- @ConditionalOnProperty (service.c) matched (OnPropertyCondition)
- @ConditionalOnBean (types: org.gotson.transitivebeandependencies.ServiceB; SearchStrategy: all) found bean 'serviceB' (OnBeanCondition)

Negative matches:

ServiceA:
Did not match:
- @ConditionalOnProperty (service.a) found different value in property 'service.a' (OnPropertyCondition)

ServiceB:
Did not match:
- @ConditionalOnBean (types: org.gotson.transitivebeandependencies.ServiceA; SearchStrategy: all) did not find any beans (OnBeanCondition)
Matched:
- @ConditionalOnProperty (service.b) matched (OnPropertyCondition)

但是,使用以下 application.yml:

service:
a: true
b: false
c: true

然后一切正常,只有 ServiceA 的一个实例被实例化,而没有创建 ServiceBServiceC bean。


使用 @Bean 而不是 @Component 的相同行为按预期工作。

MyBeans.kt:

private val logger = KotlinLogging.logger {}

@Configuration
class MyBeans {

@ConditionalOnProperty("bean.a")
@Bean
fun beanA(): BeanA {
logger.info { "A BEAN" }
return BeanA("beanA")
}

@ConditionalOnBean(BeanA::class)
@ConditionalOnProperty("bean.b")
@Bean
fun beanB(beanA: BeanA): BeanB {
logger.info { "B BEAN depends on $beanA" }
return BeanB("beanB")
}

@ConditionalOnBean(BeanB::class)
@ConditionalOnProperty("bean.c")
@Bean
fun beanC(beanB: BeanB): BeanC {
logger.info { "C BEAN depends on $beanB" }
return BeanC("beanC")
}

}

data class BeanA(val name: String)
data class BeanB(val name: String)
data class BeanC(val name: String)

使用 application.yml:

bean:
a: false
b: true
c: true

我没有实例化 BeanABeanBBeanC 类型的 bean。

这是自动配置的结果:

Negative matches:

MyBeans#beanA:
Did not match:
- @ConditionalOnProperty (bean.a) found different value in property 'bean.a' (OnPropertyCondition)

MyBeans#beanB:
Did not match:
- @ConditionalOnBean (types: org.gotson.transitivebeandependencies.BeanA; SearchStrategy: all) did not find any beans (OnBeanCondition)
Matched:
- @ConditionalOnProperty (bean.b) matched (OnPropertyCondition)

MyBeans#beanC:
Did not match:
- @ConditionalOnBean (types: org.gotson.transitivebeandependencies.BeanB; SearchStrategy: all) did not find any beans (OnBeanCondition)
Matched:
- @ConditionalOnProperty (bean.c) matched (OnPropertyCondition)

我已经设置了一个示例 repo,其中包含要重现的测试:https://github.com/gotson/spring-transitive

最佳答案

@ConditionalOnBean是一个 bean 注册阶段检查,因此需要对 ApplicationContext 中有效可用的 bean 有一个概述。 . bean 可以使用常规的 @Bean 以标准方式注册。 ,公开与方法的返回类型相同的目标类型。您可能还有FactoryBean具有更复杂的逻辑,可能导致我们必须处理的奇异设置。

无论如何,订购是关键。如果您希望 bean 类型匹配正常工作,则必须按给定顺序处理配置类。如果您有 C1提供 bean 的配置类 A仅当 bean B可用,并且所述 bean 由 C2 提供, C2 必须先运行

Spring Boot 有两个步骤解析阶段:首先我们解析所有用户的配置。完成后,我们解析自动配置的 bean 定义。自动配置本身是有序的(使用 @AutoConfigureBefore@AutoConfigureAfter )。这样,我们可以保证,如果您输入 @ConditionalOnBean在自动配置中,它将按照用户配置的预期进行处理。如果您依赖其他自动配置提供的内容,您可以使用这些注释轻松对其进行排序。

您的设置完全避开了排序,因此如果排序正确,它就可以工作,如果不正确,它就不会。 @ConditionalOnBean 的 Javadoc显然 states that

it is strongly recommended to use this condition on auto-configuration classes only.

如果您想了解更多信息,可以参加 3 小时的大学类(class),涵盖该主题 on youtube .

关于java - Spring Boot 传递 @Component 依赖与 @ConditionalOnBean,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50286863/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com