Spring框架-注入bean的子集

Spring框架-注入bean的子集,spring,dependency-injection,autowired,tagging,Spring,Dependency Injection,Autowired,Tagging,我试图在spring中控制依赖项注入,以便通过@Autowired注释只注入bean的一个子集,但我还没有找到一个提供这种行为的解决方案 假设有一个场景,其中有许多特定类型的bean,但您只希望在各种上下文中使用特定bean。@Autowired注释支持bean集合,但它似乎不支持对可以注入的各种bean应用限制(AFAIK) @配置 公共类Impl{ @自动连线(标记={“A”}) 设置beansForContextA; @自动连线(标签={“B”}) 设置beansForContextB;

我试图在spring中控制依赖项注入,以便通过
@Autowired
注释只注入bean的一个子集,但我还没有找到一个提供这种行为的解决方案

假设有一个场景,其中有许多特定类型的bean,但您只希望在各种上下文中使用特定bean。
@Autowired
注释支持bean集合,但它似乎不支持对可以注入的各种bean应用限制(AFAIK)


@配置
公共类Impl{
@自动连线(标记={“A”})
设置beansForContextA;
@自动连线(标签={“B”})
设置beansForContextB;
public void execute(){
for(Foo-Foo:someCondition?beansForContextA:beansForContextB){
...
}
}
}
这里我希望
beansForContextA
bean1
bean3
beansForContextB
bean2
bean3
。这可能是通过扩展
@Autowired
@Bean
注释来支持“标记”来实现的,但我很好奇是否有现成的解决方案,或者我必须发明自己的解决方案


或者,这是一个好主意吗?也许还有另一种方法我还没有遇到。

另一个简单的解决方案是使用新注释。通过spring收集bean,并通过新注释删除不需要的bean

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

}
@Bean
Foo bean1TypeA(){
Foo-Foo=新的Foo();
foo.setType(“typeA”);
返回新的Foo();
}
@豆子
Foo bean2TypeA(){
Foo-Foo=新的Foo();
foo.setType(“typeA”);
返回新的Foo();
}
@豆子
Foo bean1TypeB(){
Foo-Foo=新的Foo();
foo.setType(“typeB”);
返回新的Foo();
}
@豆子
Foo bean2TypeB(){
Foo-Foo=新的Foo();
foo.setType(“typeB”);
返回新的Foo();
}
@自动连线
@BeanTag(“A型”)
私人收藏类型A;
@自动连线
@BeanTag(“B型”)
私人收藏类型B;
@施工后
public void removeNotNeedType(){
//使用@BeanTag remove not need bean查找所有字段
}
注释可以实现这一点。开箱即用,您可以使用字符串来限定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() {
        ...
    }
}
有了这些自定义注释,您将得到类似这样的结果

@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) {
            ...
        }
    }
}
@配置
公共类Impl{
@自动连线
@阿斯科普
设置beansForContextA;
@自动连线
@BScope
设置beansForContextB;
public void execute(){
for(Foo-Foo:someCondition?beansForContextA:beansForContextB){
...
}
}
}

我喜欢这个解决方案,它非常简单。我个人希望看到一个只有注释的解决方案,这样注释就不会以任何方式与类型耦合,我不需要有
@PostConstruct
实现,但我还是投了赞成票。这正是我需要的。关于
@Qualifier
的信息对于简化用例也很有用,谢谢分享!
@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() {
        ...
    }
}
@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) {
            ...
        }
    }
}