Как Autowire Bean универсального типа весной?


у меня есть в зернах Item<T> который требуется для автоматического подключения в @Configuration класса.

@Configuration
public class AppConfig {

    @Bean
    public Item<String> stringItem() {
        return new StringItem();
    }

    @Bean
    public Item<Integer> integerItem() {
        return new IntegerItem();
    }

}

но когда я пытаюсь @Autowire Item<String>, Я получаю следующее исключение.

"No qualifying bean of type [Item] is defined: expected single matching bean but found 2: stringItem, integerItem"

как я должен Autowire generic type Item<T> весной?

5 51

5 ответов:

простое решение-перейти на Весна 4.0 поскольку он автоматически будет рассматривать дженерики как форму @Qualifier, как показано ниже:

@Autowired
private Item<String> strItem; // Injects the stringItem bean

@Autowired
private Item<Integer> intItem; // Injects the integerItem bean

Infact, вы можете даже autowire вложенные дженерики при введении в список, как показано ниже:

// Inject all Item beans as long as they have an <Integer> generic
// Item<String> beans will not appear in this list
@Autowired
private List<Item<Integer>> intItems;

как это работает?

новая ResolvableType класс содержит логику работы с универсальными типами. Вы можете использовать его самостоятельно, чтобы легко перемещаться и решать тип информация. Большинство методов на ResolvableType вернутся сами собой ResolvableType, например:

// Assuming 'field' refers to 'intItems' above
ResolvableType t1 = ResolvableType.forField(field); // List<Item<Integer>> 
ResolvableType t2 = t1.getGeneric(); // Item<Integer>
ResolvableType t3 = t2.getGeneric(); // Integer
Class<?> c = t3.resolve(); // Integer.class

// or more succinctly
Class<?> c = ResolvableType.forField(field).resolveGeneric(0, 0);

ознакомьтесь с примерами и учебниками по ссылкам ниже.

надеюсь, что это поможет вам.

Если вы не хотите переходить на Spring 4, вам нужно autowire по имени, как показано ниже:

@Autowired
@Qualifier("stringItem")
private Item<String> strItem; // Injects the stringItem bean

@Autowired
@Qualifier("integerItem")
private Item<Integer> intItem; // Injects the integerItem bean

стратегия Spring autowired определена в вашем файле конфигурации(приложение.XML.)

Если вы не определили, по умолчанию по типу, spring inject использует механизм отражения JDK.

такой список?Струна? а список?Предмет?, тип тот же список.класс, поэтому весной путают, как вводить.

и, как указано выше, вы должны указать @ Qualifier, чтобы сообщить spring, какой Боб должен быть введен.

Я люблю весну файла конфигурации для определения зерен, а затем аннотации.

<bean>
 <property name="stringItem">
        <list>
              <....>
        </list>
 </property>

Spring 4.0-это ответ с использованием аннотации @Qualifier. Надеюсь, это поможет

Я считаю, что это не имеет ничего общего с обобщениями... Если вы вводите два разных Боба одного типа, вам нужно предоставить квалификатор, чтобы помочь Spring идентифицировать их;

... В другом месте

@Configuration
@Bean
public Item stringItem() {
    return new StringItem();
}

@Bean
public Item integerItem() {
    return new IntegerItem();
}

Если у вас есть не общие объявления, как эти, то вам нужно добавить квалификатор, чтобы помочь Spring идентифицировать их...

@Autowired
**@Qualifier("stringItem")**
private Item item1;

@Autowired
**@Qualifier("integerItem")**
private Item item2;

конечно, в версиях 4 и выше spring рассматривает общие типы через резольверы, что очень круто...