Автоматическое подключение интерфейса Spring boot с несколькими реализациями

В обычном Spring, когда мы хотим автоматически подключить интерфейс, мы определяем его реализацию в файле контекста Spring.

  1. А как насчет весенней загрузки?
  2. как мы можем этого добиться?

в настоящее время мы только классы autowire, которые не являются интерфейсами.

Другая часть этого вопроса касается использования класса в классе Junit внутри проекта загрузки Spring.

Если мы хотим использовать CalendarUtil, например, если мы автоматически подключаем CalendarUtil, он выдаст исключение с нулевым указателем. Что делать в этом случае? Я только что инициализировал, используя «новый» ...

Так же, как в Spring (подсказка: Spring Boot на самом деле является Spring): вы определяете bean-компонент либо с помощью аннотации, либо с помощью метода, аннотированного Bean, как описано в документации Spring, и вы автоматически подключаете интерфейс, который реализует этот bean-компонент. . Если бы вы показали код, а не расплывчато его описали, все было бы проще.

JB Nizet 09.08.2018 13:48

Например, если у нас есть интерфейс под названием ChargeInterface, и у него есть две реализации: ChargeInDollars и ChrageInEuro, и у вас есть другой класс, содержащий определенную бизнес-логику под названием AmericanStoreManager, который должен использовать реализацию ChargeInDollars ChargeInterface. Вы определяете автоматически подключенный ChargeInterface, но как вы решаете, какую реализацию использовать?

user666 09.08.2018 14:16

Использование квалификаторов точно так же, как и в Spring, потому что Spring-boot - это Spring. Итак, прочтите документацию Spring и найдите «Qualifier». Или, поскольку вам все равно нужна конкретная реализация, вы можете просто автоматически подключить класс, а не интерфейс.

JB Nizet 09.08.2018 14:18
29
3
57 107
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Как упоминалось в комментариях, используя аннотацию @Qualifier, вы можете различать различные реализации, как описано в документы.

Для тестирования можно использовать тоже самое. Например:

    @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....
    }
}
Ответ принят как подходящий

Используйте аннотацию @Qualifier, чтобы различать компоненты с одним и тем же интерфейсом. Взгляните на Spring Boot документация
Кроме того, чтобы внедрить все компоненты одного и того же интерфейса, просто автопровод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);
    }

}

}

Что касается второй части вашего вопроса, посмотрите эти полезные ответы первый / второй

Для модульного теста я использовал следующие аннотации: @SpringBootTest (classes = CalendarUtil.class) @RunWith (SpringRunner.class), а затем я автоматически подключил класс.

user666 10.08.2018 07:38

У вас больше нет проблем с @Autowired ?

tsarenkotxt 10.08.2018 16:10

да, когда мы добавляем тест весенней загрузки и запускаем с аннотациями, мы можем успешно использовать аннотацию с автоматическим подключением

user666 13.08.2018 13:15

Всякий раз, когда я использую вышеуказанное в Junit вместе с Mocking, автоматическое подключение снова выходило из строя. Есть какие-нибудь советы по этому поводу? Проблема в том, что я не хочу издеваться над всеми классами, я хочу, чтобы некоторые из них были издевательскими, а другие - автоматическими. Как я могу этого добиться?

user666 29.08.2018 08:19

Мне удалось сделать это с помощью @Spy вместо Autowired в качестве аннотации в Junit и самостоятельно инициализировать класс без использования аннотаций запуска Spring.

user666 29.08.2018 08:48

попробуйте SpyBean, а также с @RunWith(SpringRunner.class), посмотрите этот пример - shekhargulati.com/2017/07/20/using-spring-boot-spybean

tsarenkotxt 29.08.2018 22:02

Когда я попытался внедрить две реализации в один компонент в разные поля, это не помогло. Внедрение с именем реализации помогло.

S.Dayneko 29.04.2020 13:50

@ S.Dayneko не могли бы вы предоставить пример кода / версию Spring? Вы используете @Qualifier("implOne") и @Qualifier("implTwo"), также он может быть квалифицирован по имени файла без аннотации @Qualifier

tsarenkotxt 29.04.2020 16:51

См. Ответ Радж Шаха ниже. Он также работает с конструктором (и без @Autowired с весны 4.3)

S.Dayneko 30.04.2020 11:57

правильно, как я писал выше - ... it can be qualified by filed name ...

tsarenkotxt 30.04.2020 15:05

Вы также можете заставить его работать, дав ему имя реализации.

Например:

@Autowired
MyService firstService;

@Autowired
MyService secondService;

Это важно!

Milan Miljus 05.08.2019 13:15

Этот подход сработал для меня, используя Qualifier вместе с аннотацией Autowired. Я тоже видел то же самое в документации docs.spring.io/spring/docs/4.3.12.RELEASE/…. Приведите пример, работает ли это для вас, как указано выше. Спасибо.

Manas 17.06.2020 11:17

Это было лучше

Jay Teli 17.07.2020 13:23

Это было хорошо, но действительно ли это инъекция зависимостей? Поскольку мы связываем переменную с именем самой службы.

yanky_cranky 11.01.2021 15:32

Другие вопросы по теме