【发布时间】:2020-03-13 14:57:28
【问题描述】:
如何在 Spring 中将 @ConditionalOnBean 与限定符一起使用?
以下独立的示例场景:我有
- 一个服务接口
SomeService - 一个适配器接口
SomeAdapter -
GreenService实现带有限定符@Green的SomeService,取决于带有限定符@Green的SomeAdapter -
SomeService的SomeService实现,带有限定符@Blue,取决于带有限定符@Blue的SomeAdapter -
SomeAdapter的可选GreenAdapter实现,带有限定符@Green -
SomeAdapter的可选BlueAdapter实现,带有限定符@Blue
@Green 限定符:
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Green { }
@Blue 限定符:
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Blue { }
绿色服务:
@Green
@Service
@ConditionalOnBean(value = SomeAdapter.class, annotation = Green.class)
public class GreenService implements SomeService {
@Autowired
@Green
private SomeAdapter adapter;
}
蓝色服务:
@Blue
@Service
@ConditionalOnBean(value = SomeAdapter.class, annotation = Blue.class)
public class BlueService implements SomeService {
@Autowired
@Blue
private SomeAdapter adapter;
}
绿色适配器:
@Green
@Component
public class GreenAdapter implements SomeAdapter {}
蓝色适配器:
@Blue
@Component
public class BlueAdapter implements SomeAdapter {}
测试以检查 bean 激活(不包含 BlueAdapter,因此 BlueService 不会被激活):
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = {GreenService.class, BlueService.class, GreenAdapter.class})
public class GreenBlueServiceTest {
@Autowired
@Green
private Optional<SomeService> greenService;
@Autowired
@Blue
private Optional<SomeService> blueService;
@Test
public void testGreen() {
assertTrue(greenService.isPresent());
}
@Test
public void testBlue() {
assertFalse(blueService.isPresent());
}
}
问题:测试无法运行,报告缺少依赖项(SomeAdapter 带有限定符 @Blue 代表 BlueService)。 @ConditionalOnBean 应该禁用 bean,因为没有带有限定符 @Blue 的 SomeAdapter,但这不起作用。
我发现当我向BlueAdapter 添加@TrueBlue 注释(与@Blue 相同,但未标记为@Annotation)并使用该注释在BlueService 上激活bean 时,它可以工作就像它应该做的那样(测试全绿色)。
总结:
- 带有所需注释的条件 bean 激活工作(原则上)
- 但是当需要的注解是
@Qualifier时它不起作用
这是一个错误,还是每个设计,以及如何实现这种依赖于 Spring 中合格 bean 的条件激活?
编辑:@bruno-leite 的回答解释了为什么它不起作用(注释和 bean 类型可以在不同的 bean 上匹配),但剩下的问题是:
如果给定类型的另一个 bean 和给定的注释(或特定限定符)存在,你如何有条件地激活一个 bean?
【问题讨论】:
标签: java spring dependency-injection