Usercase:
我们得到了一堆自动装配的bean,每个bean都注明了@Service,比如B1,B2和B3,它们具有相同的接口BInterface。
在A类的方法中,我需要根据键字符串通过接口使用其中一个,比如“b1”,“b2”和“b3”。
我可以使用hashmap Key - > BInterface,但我感兴趣的是任何Spring优雅(成语)方式来动态注入我需要的bean。我也知道getBean被认为是一种反模式。
我不知道它是否重要,但上下文定义为注释驱动。
答案 0 :(得分:1)
执行此操作的Spring方法是让您的三个bean实现三个不同的接口(或子接口),然后使用@Autowired
注释引用这三个接口。毕竟,如果三个bean具有不同的功能,那么这样做是有意义的。
你也可以拥有一个包含三个的bean,并且有@Autowired
,所以你不需要三个引用。
如果有更多相同接口的实例,我甚至不确定@Service
如何正确连线。它适用于具体的类,但我认为它不适用于许多接口的实现。
以下是我建议的一个例子:
interface BInterface{ /*...*/ }
@Service
class B1 extends BInterface{/*...*/}
@Service
class B2 extends BInterface{/*...*/}
@Service
class B3 extends BInterface{/*...*/}
@Service
class BProvider {
@Autowired
private B1 b1;
@Autowired
private B2 b2;
@Autowired
private B2 b2;
public BInterface get(String k) {
switch(k){
case "b1": return b1;
case "b2": return b2;
case "b3": return b3;
default: return b1;
}
}
}
BClient {
@Autowired
private BProvider provider;
public void doSomething(){
BInterface b = provider.get(/* one of the three */);
// use b ...
}
}
作为替代方案,您可以使BProvider
可配置,并使用XML配置使用Map<String,BInterface>
进行配置。
所以它会是:
@Service
class BProvider {
@Autowired
private Map<String,BInterface> bs;
public BInterface get(String k) {
return bs.get(k);
}
}
您必须在配置文件中定义您的地图。为此,您可以在XML文件中手动创建bean,或者我相信您可以使用BeanPostProcessor
将它们添加到集合中。
答案 1 :(得分:1)
我不确定你是否有xml配置。但你可以通过名字自动装配。在spring配置中定义3个bean b1,b2,b3,并为类中的bean名称设置setter方法
<beans>
...
<bean name="b1" class="some.package.B1" />
<bean name="b2" class="some.package.B2" />
<bean name="b3" class="some.package.B3" />
...
</beans>
Class UserOfBInterface{
BInterface b1;
BInterface b2;
BInterface b3;
public void setB1(BInterface b1){
this.b1 = b1;
}
public void setB2(BInterface b2){
this.b2 = b2;
}
public void setB3(BInterface b3){
this.b3 = b3;
}
}
另一种方法是使用@Qualifier注释而不是使用setter注入。
答案 2 :(得分:1)
您应该能够使用@Resource注释来按名称获取资源:
@Resource(name = "b1")
BInterface b1
@Resource(name = "b2")
BInterface b2
@Resource(name = "b3")
BInterface b3
答案 3 :(得分:1)
这是我能想到的最干净的方式,它确实依赖于getBeansOfType(),但只在@Configuration中运行一次,而不是在运行时“依赖项”解析它们自己的依赖项。
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class DefaultDatabaseConfiguration {
@Autowired private ApplicationContext applicationContext;
@Bean
public Map<String, MyService> services() {
return applicationContext.getBeansOfType(MyService.class);
}
}