在春季如何将@ConditionalOnBean
与预选赛一起使用?
下面是独立的示例场景:我有
SomeService
SomeAdapter
GreenService
的{{1}}实现与限定符SomeService
,取决于@Green
和限定符SomeAdapter
@Green
的{{1}}实现与限定符BlueService
,取决于SomeService
和限定符@Blue
SomeAdapter
的{{1}}的可选@Blue
实现GreenAdapter
的{{1}}的可选SomeAdapter
实现@绿色预选赛:
@Green
@Blue限定词:
BlueAdapter
GreenService:
SomeAdapter
BlueService:
@Blue
GreenAdapter:
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Green { }
BlueAdapter:
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Blue { }
测试以检查Bean的激活情况(不包含@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 {}
,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());
}
}
应该禁用Bean,因为没有SomeAdapter
带有限定符@Blue
,但这是行不通的。
我发现,当我向BlueService
添加@ConditionalOnBean
注释(与SomeAdapter
相同,但未标记为@Blue
)时,将该注释用于bean在@TrueBlue
上激活,就像应该做的一样(测试所有绿色)。
结论:
@Blue
这是错误还是按设计,并且如何实现这种条件激活取决于Spring中合格的bean ?
编辑:@ bruno-leite的答案解释了为什么它不起作用(注释和bean类型可以在不同的bean上匹配),但是剩下的问题是:
如果存在另一个给定类型和给定注释(或特定限定词)的bean,如何有条件地激活一个bean?
答案 0 :(得分:1)
请注意@ConditionalOnBean文档中指出:
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>
请注意All the requirements must be met for the condition to match, but they do not have to be met by the same bean. `
如果存在类型but they do not have to be met by the same bean.
中的任何bean加上任何用SomeAdapter
注释的bean
@Blue
因此,当您将@ConditionalOnBean(value = SomeAdapter.class, annotation = Blue.class)
bean标记为BlueService
时,您还拥有一个@Blue
,即条件通过的GreenAdapter
。它欺骗我们以为它只会与带有SomeAdapter.class
注释的SomeAdapter
匹配。
要使您的示例生效,只需从@Blue
删除@Blue
注释
看看BlueService
类上的getMatchingBeans
方法。您会看到条件是单独评估的。