Spring Boot 自动装配具有多个实现的接口
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/51766013/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spring boot autowiring an interface with multiple implementations
提问by user666
In normal Spring, when we want to autowire an interface, we define it's implementation in Spring context file. What about Spring boot? how can we achieve this? currently we only autowire classes that are not interfaces. Another part of this question is about using a class in a Junit class inside a Spring boot project. If we want to use a CalendarUtil for example, if we autowire CalendarUtil, it will throw a null pointer exception. What can we do in this case? I just initialized using "new" for now...
在普通的 Spring 中,当我们想要自动装配一个接口时,我们在 Spring 上下文文件中定义它的实现。弹簧靴呢?我们怎样才能做到这一点?目前我们只自动装配不是接口的类。这个问题的另一部分是关于在 Spring boot 项目中的 Junit 类中使用一个类。例如,如果我们想使用 CalendarUtil,如果我们自动装配 CalendarUtil,它将抛出空指针异常。在这种情况下我们能做什么?我现在刚刚使用“new”初始化......
回答by tsarenkotxt
Use @Qualifierannotation is used to differentiate beans of the same interface
Take look at Spring Boot documentation
Also, to inject all beans of the same interface, just autowireListof interface
(The same way in Spring / Spring Boot / SpringBootTest)
Example below:
使用@Qualifier注解来区分同一个接口的bean
看Spring Boot的文档
另外,要注入同一个接口的所有bean,只需要autowireList接口即可
(Spring / Spring Boot / SpringBootTest中的方法相同)
示例如下:
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
public interface MyService {
void doWork();
}
@Service
@Qualifier("firstService")
public static class FirstServiceImpl implements MyService {
@Override
public void doWork() {
System.out.println("firstService work");
}
}
@Service
@Qualifier("secondService")
public static class SecondServiceImpl implements MyService {
@Override
public void doWork() {
System.out.println("secondService work");
}
}
@Component
public static class FirstManager {
private final MyService myService;
@Autowired // inject FirstServiceImpl
public FirstManager(@Qualifier("firstService") MyService myService) {
this.myService = myService;
}
@PostConstruct
public void startWork() {
System.out.println("firstManager start work");
myService.doWork();
}
}
@Component
public static class SecondManager {
private final List<MyService> myServices;
@Autowired // inject MyService all implementations
public SecondManager(List<MyService> myServices) {
this.myServices = myServices;
}
@PostConstruct
public void startWork() {
System.out.println("secondManager start work");
myServices.forEach(MyService::doWork);
}
}
}
For the second part of your question, take look at this useful answers first/ second
回答by Raj Shah
You can also make it work by giving it the name of the implementation.
您还可以通过为其指定实现名称来使其工作。
Eg:
例如:
@Autowired
MyService firstService;
@Autowired
MyService secondService;
回答by Urosh T.
As mentioned in the comments, by using the @Qualifierannotation, you can distinguish different implementations as described in the docs.
正如评论中提到的,通过使用@Qualifier注释,您可以区分文档中描述的不同实现。
For testing, you can use also do the same. For example:
对于测试,您也可以使用同样的方法。例如:
@RunWith(SpringRunner.class)
@SpringBootTest
public class MyClassTests {
@Autowired
private MyClass testClass;
@MockBean
@Qualifier("default")
private MyImplementation defaultImpl;
@Test
public void givenMultipleImpl_whenAutowiring_thenReturnDefaultImpl() {
// your test here....
}
}

