Spring Boot自动装配具有多种实现的接口

时间:2018-08-09 11:39:43

标签: spring spring-boot junit autowired

在正常的Spring中,当我们想自动连接一个接口时,我们在Spring上下文文件中定义它的实现。那Spring Boot呢?我们怎样才能做到这一点?目前,我们仅自动装配不是接口的类。 这个问题的另一部分是关于在Spring启动项目中的Junit类中使用类。例如,如果我们要使用CalendarUtil,则如果我们自动连接CalendarUtil,它将抛出空指针异常。在这种情况下我们该怎么办?我刚刚使用“新”进行了初始化...

3 个答案:

答案 0 :(得分:8)

使用@Qualifier批注用于区分同一接口的bean
看看Spring Boot documentation
另外,要注入同一接口的所有bean,只需 autowire List接口
(与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);
    }

}

}

对于问题的第二部分,请看一下这些有用的答案first / second

答案 1 :(得分:1)

如注释中所述,通过使用@Qualifier批注,您可以区分docs中所述的不同实现。

对于测试,您也可以使用相同的方法。例如:

    @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....
    }
}

答案 2 :(得分:0)

您也可以通过为其指定实现名称来使其工作。

例如:

@Autowired
MyService firstService;

@Autowired
MyService secondService;