Задан @Qualifier, но все равно получаю NoSuchBeanDefinitionException: No unique bean of type мой_интерфейс

161
15 июня 2019, 18:40

Есть интерфейс

public interface AddressInt {
}

Класс реализующий этот интерфейс

public class AddressA implements AddressInt {
    private String state;
    private String town;
    private String street;
}

Второй класс реализующий этот интерфейс (он такой же, но это не важно)

public class AddressB implements AddressInt {
    private String state;
    private String town;
    private String street;
}

Класс, который использует тип интерфейса

public class Employee {
    private String name;
    private String position;
    @Autowired
    @Qualifier("addressA")
    private AddressInt address;
}

Главный метод

public static void main(String[] args) {
    ApplicationContext context = new ClassPathXmlApplicationContext("mySpringXMLConfig.xml");
    Employee empl = (Employee)context.getBean("employee");
    System.out.println(empl);
}

Сконфигурировано так

<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-2.5.xsd
    ">
    <!--Register AutowiredAnnotationBeanPostProcessor-->
    <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
    <!--<context:annotation-config/>-->
    <bean id="employee" class="by.Employee">
        <property name="name" value="Nick Smith"/>
        <property name="position" value="Java developer"/>
    </bean>
    <bean id="addressA" class="by.AddressA">
        <property name="state" value="NY"/>
        <property name="town" value="New York city"/>
        <property name="street" value="5"/>
    </bean>
    <bean id="addressB" class="by.AddressB">
        <property name="state" value="IL"/>
        <property name="town" value="Chicago"/>
        <property name="street" value="37"/>
    </bean>
</beans>

Классика жанра и все просто, но при выполнении получаем

org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [by.AddressInt] is defined: expected single matching bean but found 2: [addressA, addressB]

Гуглил. У других людей вижу причины отказа, у себя не вижу. Квалификатор пробовал задавать разными способами (и в xml, и свою аннотацию писать), но итог один. В чем же секрет?

Answer 1

AutowiredAnnotationBeanPostProcessor не поддерживает аннотацию @Qualifier. Чтобы она обрабатывалась, нужно вместо него использовать <context:annotation-config/>.

Но есть один нюанс.

<context:annotation-config/> работает на версии Java 5 и выше. Однако Spring 2.5.6 не знает о существовании Java выше версии 7, и всё что не 5, 6 или 7 он считает Java 4. Поэтому, если вы под Java 8 запустите проект с <context:annotation-config/> и Spring 2.5.6, вы получите изумительнейшую ошибку Context namespace element 'annotation-config' and its parser class [org.springframework.context.annotation.AnnotationConfigBeanDefinitionParser] are only available on JDK 1.5 and higher.

Решить это можно целыми четырьмя способами. Первый, наиболее предпочтительный - обновить Spring. Актуальная версия - 5.1.3, но поддержка Java 8 появилась в 4.0.3. Если по каким-то причинам вам это не подходит, то второй вариант - добавить к одному из объявлений бинов address* свойство primary="true". Тогда AutowiredAnnotationBeanPostProcessor будет использовать именно его везде, где есть больше одного кандидата этого типа. Если же вы хотите в одном месте использовать addressA, а в другом - addressB, а обновлять Spring вам не позволяют обстоятельства, то к вашим услугам третий вариант - отказаться от @Autowired и явно инжектировать бины в конфиге. Ну и четвёртый вариант - запускать вашу программу под Java 5-7. Крайне не рекомендую так делать, потому что JRE этих версий не поддерживаются, и могут содержать уязвимости и баги, которые никогда уже не исправят.

READ ALSO
Spring Boot как добавить соединение с БД в контекст приложения

Spring Boot как добавить соединение с БД в контекст приложения

Есть приложение на спринг бутеЯ хочу написать класс, который будет делать реконнект к RethinkDB, если база упала

152
Как можно сделать противофазу звука с микрофона?

Как можно сделать противофазу звука с микрофона?

Как можно сделать противофазу звука с микрофона и воспроизвести через наушники?

170
Подключение android к Raspberry Pi

Подключение android к Raspberry Pi

Перед мной стоит задача разработать приложение для android, целью которого является подключение android-устройства к raspberryКаким образом организовать...

133