java - 如何为弹簧限定符实现 OR 逻辑?
问题描述
我有以下配置:
@Qualifier1
@Qualifier2
@Bean
public MyBean bean1(){...}
@Qualifier2
@Qualifier3
@Bean
public MyBean bean2(){...}
@Qualifier1
@Qualifier2
@Qualifier3
@Bean
public MyBean bean3(){...}
@Qualifier3
@Bean
public MyBean bean4(){...}
@Qualifier1
@Bean
public MyBean bean5(){...}
它是注射的地方:
@Qualifier2
@Qualifier3
@Autowired:
private List<MyBean> beans;
默认情况下,springAND
为每个使用逻辑@Qualifier
所以bean2
会bean3
被注入。
但我想对这些东西有逻辑,OR
所以我希望豆子被注入bean1
bean2
bean3
bean4
我怎样才能实现它?
附言
@Qualifier
注释是不可重复的,所以我必须为每个注释创建元注释:
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Qualifier1 {
}
解决方案
如果您使用标记接口而不是限定符会怎样?例如:
public class MyBean1 extends MyBean implements Marker1 {}
public class MyBean2 extends MyBean implements Marker2 {}
public class MyBean12 extends MyBean implements Marker1, Marker2 {}
然后使用这个:
@Bean
public MyBean1 myBean1() {
//...
}
@Bean
public MyBean2 myBean2() {
//...
}
@Bean
public MyBean12 myBean12() {
//...
}
还有这个:
@Autowired private List<Marker1> myBeans;
你会得到一个beanmyBean1
的列表。myBean12
为此:
@Autowired private List<Marker2> myBeans;
你会得到一个beanmyBean2
的列表。myBean12
这行得通吗?
更新我
自定义 FactoryBean
我实现了 TagsFactoryBean类和@Tags注释,您可以使用它们来解决您的任务(我希望 :))。
@Tags
首先,用注释标记你的 bean :
@Tags({"greeting", "2letters"})
@Bean
public Supplier<String> hi() {
return () -> "hi";
}
@Tags({"parting", "2letters"})
@Bean
public Supplier<String> by() {
return () -> "by";
}
@Tags("greeting")
@Bean
public Supplier<String> hello() {
return () -> "hello";
}
@Tags("parting")
@Bean
public Supplier<String> goodbye() {
return () -> "goodbye";
}
@Tags("other")
@Bean
public Supplier<String> other() {
return () -> "other";
}
然后准备TagsFactoryBean
:
@Bean
public TagsFactoryBean words() {
return TagsFactoryBean.<Supplier>builder()
.tags("greeting", "other")
.type(Supplier.class)
.generics(String.class)
.build();
}
这tags
是一组应选择其 bean 的所需标记,type
是选定的 bean 类型,并且generics
是 bean 的泛型类型的数组。最后一个参数是可选的,仅当您的 bean 是通用的时才应使用。
然后您可以将它与@Qualifier
注释一起使用(否则 Spring 会注入所有Supplier<String>
类型的 bean):
@Autowired
@Qualifier("words")
private Map<String, Supplier<String>> beans;
Mapbeans
将包含三个 bean:hi
和hello
(other
它们的名称是 Map 的键,它们的实例是它的值)。
您可以在测试中找到更多使用示例。
更新二
自定义 AutowireCandidateResolver
感谢@bhosleviraj 的推荐,我实现了 TaggedAutowireCandidateResolver,它简化了自动装配所需 bean 的过程。只需使用相同的标签标记您的 bean 和自动装配的集合,您就会将它们注入集合中:
@Autowired
@Tags({"greeting", "other"})
private Map<String, Supplier<String>> greetingOrOther;
@Configuration
static class Beans {
@Tags({"greeting", "2symbols", "even"})
@Bean
public Supplier<String> hi() {
return () -> "hi";
}
@Tags({"parting", "2symbols", "even"})
@Bean
public Supplier<String> by() {
return () -> "by";
}
@Tags({"greeting", "5symbols", "odd"})
@Bean
public Supplier<String> hello() {
return () -> "hello";
}
@Tags({"parting", "7symbols", "odd"})
@Bean
public Supplier<String> goodbye() {
return () -> "goodbye";
}
@Tags({"other", "5symbols", "odd"})
@Bean
public Supplier<String> other() {
return () -> "other";
}
}
您不仅可以使用 Map 来注入 bean,还可以使用其他 Collections。
要使其工作,您必须CustomAutowireConfigurer
在应用程序中注册一个 bean 并为其提供TaggedAutowireCandidateResolver
:
@Configuration
public class AutowireConfig {
@Bean
public CustomAutowireConfigurer autowireConfigurer(DefaultListableBeanFactory beanFactory) {
CustomAutowireConfigurer configurer = new CustomAutowireConfigurer();
beanFactory.setAutowireCandidateResolver(new TaggedAutowireCandidateResolver());
configurer.postProcessBeanFactory(beanFactory);
return configurer;
}
}
更多使用示例请参阅此测试。
推荐阅读
- reactjs - 如何正确地将状态作为道具从一个组件传递到另一个组件?
- python - 从数据框中删除重叠/相同的事务
- python - 为什么 dj-database-url 给我一个错误:需要一个类似字节的对象,而不是“str”,我该如何解决这个问题?
- ios - Swift Map ARRAYS 按日期数组
- python - Python映射对象在减少后变为空
- eclipse - 为什么 Eclipse 拒绝将 Java 类作为 AWS SAM Local 而不仅仅是 Java 运行?
- d3.js - d3.js 在聚集图表上格式化数据标签
- c# - 如何从另一个表单填充 datagridview 单元格?C#
- c# - 从应用商店下载时,Xamarin.iOS 应用在使用 iPhone5 启动时崩溃。DYLD,库未加载错误。-+
- symfony - Symfony 4 学说即使在开发环境中也使用缓存