当将 @Profile与自定义Condition组合使用时,Spring Boot的 @Conditional Bean未被拾取 — NoSuchBeanDefinitionException
问题
我正在构建一个Spring Boot应用,其中一个 TreeRepository bean必须在两个条件同时满足时被激活:一个Spring @Profile 和一个自定义 @Conditional。存储库定义如下:
java
@Repository
@Profile("mongo")
@Conditional(MongoCondition.class)
@Primary
public class MongoTreeRepository implements TreeRepository {
// ...
}
MongoCondition 读取一个名为properties的属性
public class MongoCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
String repoType = context.getEnvironment().getProperty("app.storage");
return "mongo".equalsIgnoreCase(repoType);
}
}
我的 application-mongo.properties 设置:
properties
spring.profiles.active=mongo
app.storage=mongo
观察到的行为
当同时存在 @Profile("mongo") 与 @Conditional(MongoCondition.class) 时,应用在启动阶段有时会因为 NoSuchBeanDefinitionException: No qualifying bean of type 'TreeRepository' 而失败,尽管活动的配置文件是 mongo,且 app.storage=mongo 已被设置。移除任一注解即可使其正常工作。
期望的行为
两个注解都应该评估为 true,并且bean应按正常方式注册。
我尝试过
- 通过在
ApplicationRunner中打印来验证该属性已正确加载 - 尝试用第二个
@Conditional替换@Profile,手动检查活动配置文件——结果偶尔仍然相同 - 检查了循环依赖——未发现循环依赖
问题
在Spring Boot中,@Profile 与 @Conditional 的评估之间是否存在已知的排序问题?我是否应该将两者的检查合并到一个 Condition 类中以避免冲突?@Primary 是否会与条件评估互动?
解决方案
从你的问题来看,你说 spring.profiles.active=mongo 已在 application-mongo.properties 中被设置。这存在问题,因为根据 文档 这被认为是无效的:
spring.profiles.active和spring.profiles.default只能在非配置文件相关的文档中使用。这意味着它们不能被包含在 profile specific files 或由spring.config.activate.on-profile启用的文档中。
在Spring Boot中,@Profile与 @Conditional的评估之间是否存在已知的排序问题?
没有,不存在排序问题。@Profile 实现为一个 @Conditional,请参阅它的源代码。按你预期的行为,“这两个注解都应当评估为true,bean应该正常注册”。