code

제네릭 유형의 Bean을 Autowire하는 방법

codestyles 2020. 11. 14. 10:15
반응형

제네릭 유형의 Bean을 Autowire하는 방법 봄에?


클래스 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"

Item<T>Spring에서 제네릭 유형 어떻게 Autowire해야 합니까?


간단한 해결책은 다음 과 같이 제네릭을 형식으로 자동 고려하므로 Spring 4.0 으로 업그레이드 하는 것입니다 @Qualifier.

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

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

실제로 아래와 같이 목록에 삽입 할 때 중첩 된 제네릭을 자동으로 연결할 수도 있습니다.

// 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로 업그레이드하고 싶지 않다면 아래와 같이 이름으로 자동 연결해야합니다.

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

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

Spring autowired 전략은 구성 파일 (application.xml)에 정의되어 있습니다.

정의하지 않은 경우 기본값은 유형, 스프링 주입은 JDK 반사 메커니즘을 사용합니다.

그래서 목록? 문자열? 및 List? Item ?, 유형은 동일한 List.class이므로 주입 방법을 혼동합니다.

그리고 위의 사람 응답과 같이, 당신은 어떤 빈이 주입되어야 하는지를 스프링에게 알려주기 위해 포인트 @Qualifier이어야합니다.

나는 Annotation보다는 bean을 정의하는 spring configration 파일을 좋아합니다.

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


나를위한 일입니다 !!


        List<String> listItem= new ArrayList<>();

        ResolvableType resolvableType = ResolvableType.forClassWithGenerics(List.class, String.class);
        RootBeanDefinition beanDefinition = new RootBeanDefinition();
        beanDefinition.setTargetType(resolvableType);
        beanDefinition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
        beanDefinition.setAutowireCandidate(true);

        DefaultListableBeanFactory bf = (DefaultListableBeanFactory) configurableWebApplicationContext.getBeanFactory();

        bf.registerBeanDefinition("your bean name", beanDefinition);
        bf.registerSingleton("your bean name", listItem);

Spring 4.0은 @Qualifier 주석 사용에 대한 답입니다. 도움이 되었기를 바랍니다


I believe it has nothing to with generics... If you are injecting two different beans of same type then you need to provide a qualifier to help Spring identify them;

... Elsewhere

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

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

If you have a non-generic declarations like these then you need to add qualifier to help Spring identify them...

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

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

Of course, in versions 4 and above spring considers the Generic Types through the resolvers which is very cool...

참고URL : https://stackoverflow.com/questions/22603291/how-to-autowire-bean-of-generic-type-t-in-spring

반응형