gpt4 book ai didi

java - Spring 以合格的 bean 为条件

转载 作者:行者123 更新时间:2023-12-02 08:52:54 24 4
gpt4 key购买 nike

如何在 Spring 中使用带有限定符的 @ConditionalOnBean

以下独立示例场景:我有

  • 服务接口(interface)SomeService
  • 适配器接口(interface)SomeAdapter
  • 带有限定符 @GreenSomeServiceGreenService 实现,依赖于带有限定符 @ 的 SomeAdapter绿色
  • 带有限定符 @BlueSomeServiceBlueService 实现,依赖于带有限定符 @ 的 SomeAdapter蓝色
  • 带有限定符 @GreenSomeAdapter 的可选 GreenAdapter 实现
  • 带有限定符 @BlueSomeAdapter 的可选 BlueAdapter 实现

@绿色限定符:

@Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Green { }

@蓝色限定符:

@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 将不会处于 Activity 状态):

@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,因为没有带有限定符 @BlueSomeAdapter,但这不起作用。

我发现当我向BlueAdapter,并使用该注释在 BlueService 上激活 bean,它的工作方式就像它应该做的那样(测试全绿色)。

结论:

  • 带有所需注释的条件 Bean 激活有效(原则上)
  • 但是,当所需的注释是 @Qualifier 时,它不起作用

这是一个错误,还是按照设计,如何实现依赖于 Spring 中合格 bean 的条件激活

<小时/>

编辑:@bruno-leite的答案解释了为什么它不起作用(注释和bean类型可以在不同的bean上匹配),但剩下的问题是:

如果存在给定类型的另一个 Bean 和给定的注释(或特定限定符),如何有条件地激活一个 Bean?

最佳答案

请注意@ConditionalOnBean文档说:

All the requirements must be met for the condition to match, but they do not have to be met by the same bean. ` 

请注意“”部分,但它们不必由同一个 bean 满足。

<小时/>

如果存在 SomeAdapter 类型的任何 bean 以及用 @Blue 注释的 any bean,则以下条件将匹配

@ConditionalOnBean(value = SomeAdapter.class, annotation = Blue.class)

因此,当您有一个用 @Blue 注解的 BlueService bean 时,您还有一个 GreenAdapter,它是一个 SomeAdapter。 class 条件通过。它欺骗我们,让我们认为它只会匹配带有 @Blue 注释的 SomeAdapter

要使您的示例正常工作,只需从 BlueService 中删除 @Blue 注释

<小时/>

查看 OnBeanCondition 类上的 getMatchingBeans 方法。您将看到条件是单独评估的。

关于java - Spring 以合格的 bean 为条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60672681/

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