Конфликт автопроводки в ядре Spring с конфигурацией xml

Взяв за ссылку пост Spring @Autowired и @Qualifier

У нас есть этот пример, чтобы исправить конфликт автопроводки:

public interface Vehicle {
     public void start();
     public void stop();
}

Есть два bean-компонента, Car и Bike, реализующие Vehicle интерфейс.

@Component(value = "car")
public class Car implements Vehicle {

     @Override
     public void start() {
           System.out.println("Car started");
     }

     @Override
     public void stop() {
           System.out.println("Car stopped");
     }
 }

@Component(value = "bike")
public class Bike implements Vehicle {

     @Override
     public void start() {
          System.out.println("Bike started");
     }

     @Override
     public void stop() {
          System.out.println("Bike stopped");
     }
}

@Component
public class VehicleService {

    @Autowired
    @Qualifier("bike")
    private Vehicle vehicle;

    public void service() {
         vehicle.start();
         vehicle.stop();
    }
}

Это очень хороший пример решения этой проблемы.

Но когда у меня такая же проблема, но без этих балисов в контексте приложения:

<context:component-scan></context:component-scan>
<context:annotation-config></context:annotation-config>

Все вопросы решаются с помощью аннотации @Qualifier, но в моем случае мы не используем бальзам, разрешающий использовать аннотацию.

Вопрос в том :

Как я могу исправить эту проблему, просто используя конфигурацию в контексте приложения, вот и все, без использования аннотаций?

Я много искал и Я обнаружил, что люди говорят об атрибуте autowire в объявлении bean-компонента <bean id = "dao" class = "package.IDao" autowire = "byName"></bean>, и мне нужно больше объяснений по этому поводу.

dzone.com/articles/…
Med Elgarnaoui 08.04.2019 17:59
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
9
1
1 661
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы можете использовать @Начальный вместо @Qualifier

@Primary
@Component(value = "bike")
public class Bike implements Vehicle {

we use @Primary to give higher preference to a bean when there are multiple beans of the same type.

We can use @Primary directly on the beans

Вы также можете установить основной атрибут в XML:

property has primary attribute:

<bean primary = "true|false"/>

If a @Primary-annotated class is declared via XML, @Primary annotation metadata is ignored, and is respected instead.

Ответ принят как подходящий

How can I fix this issue just using the configuration in application context?

Вы можете использовать тег qualifier, как показано ниже (см. https://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/beans.html#beans-autowired-annotation-qualifiers)

<context:annotation-config/>
  <beans>
    <bean class = "your_pkg_route.Vehicle">
      <qualifier value = "bike"/>
    </bean>
  </beans>
</context:annotation-config>

I found people talking about autowire attribute in the bean declaration and I need more explanation about it

Использование аннотации

@Autowired, используемый в методе объявления bean-компонента, вводит определенные зависимости (другим) объявленным bean-компонентом. Теперь, если ваши зависимости находятся в том же контексте вашего приложения, вам вообще не нужно использовать аннотацию @Autowired, потому что Spring может понять их самостоятельно. Итак, если ваши зависимости находятся вне контекста вашего приложения, вы можете его использовать.

Например, возьмите в качестве ссылки приведенный ниже код:

@Autowired
@Bean
public MyBean getMybean(Dependency1 depdency1, Dependency2 depdency2) {
    return new MyBean(depdency1.getSomeStuff(), depdency2.getSomeOtherStuff());
}

Здесь @Autowired найдет экземпляр Dependency1 и Dependency2 и предоставит их для создания экземпляра MyBean.

Использование xml-конфигурации

From Про Spring 5... Spring поддерживает пять режимов автоматического подключения.

  • byName: при использовании byName автосвязывания Spring пытается связать каждое свойство с компонентом с тем же именем. Таким образом, если целевой компонент имеет свойство с именем foo и компонент foo определен в ApplicationContext, компонент foo назначается свойству foo цели.
  • byType: при использовании byType автосвязывания Spring пытается связать каждый из свойств целевого компонента путем автоматического использования компонента того же типа в ApplicationContext.
  • constructor: это работает так же, как byType проводка, за исключением того, что для выполнения инъекции используются конструкторы, а не сеттеры. Spring пытается сопоставить максимально возможное количество аргументов в конструкторе. Таким образом, если ваш bean-компонент имеет два конструктора, один из которых принимает String, а другой принимает String и Integer, и у вас есть как String, так и Integer bean-компонент в вашем ApplicationContext, Spring использует конструктор с двумя аргументами.
  • default: Spring будет выбирать между режимами constructor и byType. автоматически. Если ваш компонент имеет конструктор по умолчанию (без аргументов), Spring использует byType; в противном случае он использует конструктор.
  • no: это значение по умолчанию

Итак, в вашем случае вам нужно будет сделать что-то вроде этого (НО, я бы НЕ рекомендовал это. Почему?, вам нужно будет объявить класс Vehicle как bean-компонент и компонент, что неверно, см. Spring: @Component против @Bean. С другой стороны Я не уверен, что вы могли бы использовать его, просто объявив его как bean-компонент):

// xml config
<context:annotation-config/>
  <beans>

    // use the primary tag here too! in order to say this the primary bean
    // this only works when there are only two implementations of the same interface
    <bean id = "bike" primary = "true" class = "your_pkg_route.Bike"/>
    <bean id = "car" class = "your_pkg_route.Car"/>         

    <bean autowire = "byName" class = "your_pkg_route.VehicleService"/>

  <beans>
</context:annotation-config>

// VehicleService
@Component
public class VehicleService {

    private Vehicle bike;   // call attribute 'bike' so it is autowired by its name

    public void service() {
         //...
    }
}

Как вы можете видеть, попытка сделать это с помощью конфигурации xml сопряжена с множеством сложностей, поэтому я бы порекомендовал вам использовать параметр аннотации, если это возможно.

Похожие сообщения:

PS: я не тестировал ни один из опубликованных кодов.

Спасибо за помощь

Med Elgarnaoui 18.04.2019 11:12

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