春天猫rtsy
如果您使用Spring框架超过一个星期,那么您可能已经知道此功能。 假设您有多个bean实现了给定的接口。 尝试仅自动连接此类接口的一个bean注定会失败,因为Spring不知道您需要哪个特定实例。 您可以通过使用@Primary
批注来指定一个优先于其他实现的“ 最重要 ”实现,从而解决此问题。 但是在许多合法的用例中,您想注入所有实现了上述接口的bean。 例如,您有多个验证器,所有验证器都需要在业务逻辑或要同时执行的几种算法实现之前执行。 自动发现所有的实现在运行时是一个奇妙的例证打开/关闭原理 :您可以轻松地添加新的行为,以业务逻辑(验证,算法,策略-对扩展开放 ),无需触摸的业务逻辑本身(修改关闭 )。
万一我有一个快速的介绍,请随时直接跳到后续章节。 因此,让我们举一个具体的例子。 假设您有一个StringCallable
接口和多个实现:
interface StringCallable extends Callable<String> { }
@Component
class Third implements StringCallable {
@Override
public String call() {
return "3";
}
}
@Component
class Forth implements StringCallable {
@Override
public String call() {
return "4";
}
}
@Component
class Fifth implements StringCallable {
@Override
public String call() throws Exception {
return "5";
}
}
现在,我们可以将List<StringCallable>
, Set<StringCallable>
或Map<String, StringCallable>
( String
代表bean名称)注入其他任何类。 为了简化,我将注入一个测试用例:
@SpringBootApplication public class Bootstrap { }
@ContextConfiguration(classes = Bootstrap)
class BootstrapTest extends Specification {
@Autowired
List<StringCallable> list;
@Autowired
Set<StringCallable> set;
@Autowired
Map<String, StringCallable> map;
def 'injecting all instances of StringCallable'() {
expect:
list.size() == 3
set.size() == 3
map.keySet() == ['third', 'forth', 'fifth'].toSet()
}
def 'enforcing order of injected beans in List'() {
when:
def result = list.collect { it.call() }
then:
result == ['3', '4', '5']
}
def 'enforcing order of injected beans in Set'() {
when:
def result = set.collect { it.call() }
then:
result == ['3', '4', '5']
}
def 'enforcing order of injected beans in