Spring 框架 - 注入 bean 的子集
Spring Framework - Inject subset of beans
我正在尝试控制 spring 中的依赖项注入,以便 @Autowired
注释只注入一部分 bean,但我还没有遇到提供此功能的解决方案行为。
想象一个场景,有很多特定类型的 bean,但您只想在各种上下文中使用某些 bean。 @Autowired
注释支持 bean 集合,但它似乎不支持对可以注入的各种 bean 应用限制(AFAIK)。
@Autowired
Set<Foo> beansForContextA;
@Autowired
Set<Foo> beansForContextB;
以上代码会将同一组 bean 注入到 beansForContextA
和 beansForContextB
中。我想要一种方法来区分哪些 bean 被注入到它各自的 属性 中。 spring 中是否内置了支持此用例的内容?
考虑以下伪代码来更清楚地说明期望:
@Configuration
public class Config {
@Bean(tags = {"A"})
Foo bean1() {
...
}
@Bean(tags = {"B"})
Foo bean2() {
...
}
@Bean(tags = {"A", "B"})
Foo bean3() {
...
}
}
@Configuration
public class Impl {
@Autowired(tags = {"A"})
Set<Foo> beansForContextA;
@Autowired(tags = {"B"})
Set<Foo> beansForContextB;
public void execute() {
for (Foo foo : someCondition ? beansForContextA : beansForContextB) {
...
}
}
}
这里我希望 beansForContextA
有 bean1
和 bean3
和 beansForContextB
有 bean2
和 bean3
。这可以通过扩展 @Autowired
和 @Bean
注释来支持 "tags" 来实现,但我很好奇是否已经有解决方案,或者我是否必须发明自己的解决方案?
或者,这是个好主意吗?也许还有另一种方法我还没有遇到过。
另一个简单的解决方案是使用 spring 的新 annotation.collect beans 并通过新注释删除不需要的 beans。
public @interface BeanTag {
String value();
}
使用方法
@Bean
Foo bean1TypeA() {
Foo foo = new Foo();
foo.setType("typeA");
return new Foo();
}
@Bean
Foo bean2TypeA() {
Foo foo = new Foo();
foo.setType("typeA");
return new Foo();
}
@Bean
Foo bean1TypeB() {
Foo foo = new Foo();
foo.setType("typeB");
return new Foo();
}
@Bean
Foo bean2TypeB() {
Foo foo = new Foo();
foo.setType("typeB");
return new Foo();
}
@Autowired
@BeanTag("typeA")
private Set<Foo> collectionTypeA;
@Autowired
@BeanTag("typeB")
private Set<Foo> collectionTypeB;
@PostConstruct
public void removeNotNeedType(){
// find all the field with @BeanTag remove not need bean
}
@Qualifier注解可以实现这一点。开箱即用,您可以使用字符串来限定 bean 和注入点:
@Autowired
@Qualifier("a")
Set<Foo> beansForContextA;
@Autowired
@Qualifier("b")
Set<Foo> beansForContextB;
@Configuration
public class Config {
@Bean
@Qualifier("a")
Foo bean1() {
...
}
@Bean
@Qualifier("b")
Foo bean2() {
...
}
}
然而,这对您的情况不起作用,因为 @Qualifier
的多个实例不能出现在同一个地方。 You have to create custom annotations which are annotated with Qualifier
and use those instead of @Qualifier
and a string name.
@Target(value={FIELD,METHOD,PARAMETER,TYPE,ANNOTATION_TYPE})
@Retention(value=RUNTIME)
@Inherited
@Qualifier
public interface AScope
@Target(value={FIELD,METHOD,PARAMETER,TYPE,ANNOTATION_TYPE})
@Retention(value=RUNTIME)
@Inherited
@Qualifier
public interface BScope
使用这些自定义注释,您最终会得到这样的结果。
@Configuration
public class Config {
@Bean
@AScope
Foo bean1() {
...
}
@Bean
@BScope
Foo bean2() {
...
}
@Bean
@AScope
@BScope
Foo bean3() {
...
}
}
在注入点:
@Configuration
public class Impl {
@Autowired
@AScope
Set<Foo> beansForContextA;
@Autowired
@BScope
Set<Foo> beansForContextB;
public void execute() {
for (Foo foo : someCondition ? beansForContextA : beansForContextB) {
...
}
}
}
我正在尝试控制 spring 中的依赖项注入,以便 @Autowired
注释只注入一部分 bean,但我还没有遇到提供此功能的解决方案行为。
想象一个场景,有很多特定类型的 bean,但您只想在各种上下文中使用某些 bean。 @Autowired
注释支持 bean 集合,但它似乎不支持对可以注入的各种 bean 应用限制(AFAIK)。
@Autowired
Set<Foo> beansForContextA;
@Autowired
Set<Foo> beansForContextB;
以上代码会将同一组 bean 注入到 beansForContextA
和 beansForContextB
中。我想要一种方法来区分哪些 bean 被注入到它各自的 属性 中。 spring 中是否内置了支持此用例的内容?
考虑以下伪代码来更清楚地说明期望:
@Configuration
public class Config {
@Bean(tags = {"A"})
Foo bean1() {
...
}
@Bean(tags = {"B"})
Foo bean2() {
...
}
@Bean(tags = {"A", "B"})
Foo bean3() {
...
}
}
@Configuration
public class Impl {
@Autowired(tags = {"A"})
Set<Foo> beansForContextA;
@Autowired(tags = {"B"})
Set<Foo> beansForContextB;
public void execute() {
for (Foo foo : someCondition ? beansForContextA : beansForContextB) {
...
}
}
}
这里我希望 beansForContextA
有 bean1
和 bean3
和 beansForContextB
有 bean2
和 bean3
。这可以通过扩展 @Autowired
和 @Bean
注释来支持 "tags" 来实现,但我很好奇是否已经有解决方案,或者我是否必须发明自己的解决方案?
或者,这是个好主意吗?也许还有另一种方法我还没有遇到过。
另一个简单的解决方案是使用 spring 的新 annotation.collect beans 并通过新注释删除不需要的 beans。
public @interface BeanTag {
String value();
}
使用方法
@Bean
Foo bean1TypeA() {
Foo foo = new Foo();
foo.setType("typeA");
return new Foo();
}
@Bean
Foo bean2TypeA() {
Foo foo = new Foo();
foo.setType("typeA");
return new Foo();
}
@Bean
Foo bean1TypeB() {
Foo foo = new Foo();
foo.setType("typeB");
return new Foo();
}
@Bean
Foo bean2TypeB() {
Foo foo = new Foo();
foo.setType("typeB");
return new Foo();
}
@Autowired
@BeanTag("typeA")
private Set<Foo> collectionTypeA;
@Autowired
@BeanTag("typeB")
private Set<Foo> collectionTypeB;
@PostConstruct
public void removeNotNeedType(){
// find all the field with @BeanTag remove not need bean
}
@Qualifier注解可以实现这一点。开箱即用,您可以使用字符串来限定 bean 和注入点:
@Autowired
@Qualifier("a")
Set<Foo> beansForContextA;
@Autowired
@Qualifier("b")
Set<Foo> beansForContextB;
@Configuration
public class Config {
@Bean
@Qualifier("a")
Foo bean1() {
...
}
@Bean
@Qualifier("b")
Foo bean2() {
...
}
}
然而,这对您的情况不起作用,因为 @Qualifier
的多个实例不能出现在同一个地方。 You have to create custom annotations which are annotated with Qualifier
and use those instead of @Qualifier
and a string name.
@Target(value={FIELD,METHOD,PARAMETER,TYPE,ANNOTATION_TYPE})
@Retention(value=RUNTIME)
@Inherited
@Qualifier
public interface AScope
@Target(value={FIELD,METHOD,PARAMETER,TYPE,ANNOTATION_TYPE})
@Retention(value=RUNTIME)
@Inherited
@Qualifier
public interface BScope
使用这些自定义注释,您最终会得到这样的结果。
@Configuration
public class Config {
@Bean
@AScope
Foo bean1() {
...
}
@Bean
@BScope
Foo bean2() {
...
}
@Bean
@AScope
@BScope
Foo bean3() {
...
}
}
在注入点:
@Configuration
public class Impl {
@Autowired
@AScope
Set<Foo> beansForContextA;
@Autowired
@BScope
Set<Foo> beansForContextB;
public void execute() {
for (Foo foo : someCondition ? beansForContextA : beansForContextB) {
...
}
}
}