복붙노트

[SPRING] 봄은``유형의 하나 이상의 콩이있다, autowire가 없습니다

SPRING

봄은``유형의 하나 이상의 콩이있다, autowire가 없습니다

여기에 내 질문 : 저는 기본 인터페이스와 두 개의 구현 클래스가 있습니다.

그리고 서비스 클래스는 기본 인터페이스에 대한 종속성이, 코드는 다음과 같다 :

@Component
public interface BaseInterface {}
@Component
public class ClazzImplA implements  BaseInterface{}
@Component
public class ClazzImplB implements  BaseInterface{}

그리고 구성은 다음과 같이이다 :

@Configuration
public class SpringConfig {
    @Bean
    public BaseInterface clazzImplA(){
        return new ClazzImplA();
    }

    @Bean
    public BaseInterface clazzImplB(){
        return new ClazzImplB();
    }
}

서비스 클래스는 코드는 다음과 같다 logic.And 일부 비즈니스로하는 구현 autowire하기로 결정합니다 기본 인터페이스에 종속

@Service
@SpringApplicationConfiguration(SpringConfig.class)
public class AutowiredClazz {
    @Autowired
    private BaseInterface baseInterface;

    private AutowiredClazz(BaseInterface baseInterface){
        this.baseInterface = baseInterface;
    }
}

그리고 IDEA는 예외를 throw :하지 autowire.There이 BaseInterface 유형의 하나 이상의 콩입니다 수 있습니다.

이 예선 @ 사용하여 해결할 수 있지만, 그러나이 상황에서 나는 종속 클래스를 선택할 수 없습니다.

@Autowired
@Qualifier("clazzImplA")
private BaseInterface baseInterface;

나는 봄 문서를 읽고는 생성자 의존성 주입을 제공하기 위해 노력하지만 여전히 문제로 혼란스러워하고 있습니다.

그 누구도 날 도와 드릴까요?

해결법

  1. ==============================

    1.봄은 구성 클래스에 이러한 수정 사항을 적용, 유선됩니다 정확한되는 콩 지정하여 혼란을 제거하기 위해 @Autowired와 함께 당신이 @Qualifier 어노테이션을 사용할 수 있도록 당신이 구성 클래스에서 선언 한 2 콩 사이에 혼란

    봄은 구성 클래스에 이러한 수정 사항을 적용, 유선됩니다 정확한되는 콩 지정하여 혼란을 제거하기 위해 @Autowired와 함께 당신이 @Qualifier 어노테이션을 사용할 수 있도록 당신이 구성 클래스에서 선언 한 2 콩 사이에 혼란

    @Configuration
    public class SpringConfig {
        @Bean(name="clazzImplA")
        public BaseInterface clazzImplA(){
            return new ClazzImplA();
        }
    
        @Bean(name="clazzImplB")
        public BaseInterface clazzImplB(){
            return new ClazzImplB();
        }
    }
    

    다음 @Autowired 주석에

    @Service
    @SpringApplicationConfiguration(SpringConfig.class)
    public class AutowiredClazz {
        @Autowired
        @Qualifier("the name of the desired bean")
        private BaseInterface baseInterface;
    
        private AutowiredClazz(BaseInterface baseInterface){
            this.baseInterface = baseInterface;
        }
    }
    
  2. ==============================

    2.이 스프링 프레임 워크 만 사용하여 해결할 수 없습니다. 당신은 어떤 논리에 따라 당신이 BaseInterface의 인스턴스를 필요가 있다고 언급했다. 이 유스 케이스는 공장 패턴을 사용하여 해결할 수 있습니다. 실제로 BaseInterface의 팩토리 인 콩 만들기

    이 스프링 프레임 워크 만 사용하여 해결할 수 없습니다. 당신은 어떤 논리에 따라 당신이 BaseInterface의 인스턴스를 필요가 있다고 언급했다. 이 유스 케이스는 공장 패턴을 사용하여 해결할 수 있습니다. 실제로 BaseInterface의 팩토리 인 콩 만들기

    @Component
    public class BaseInterfaceFactory{
    
      @Autowired
      @Qualifier("clazzImplA")
      private BaseInterface baseInterfaceA;
    
      @Autowired
      @Qualifier("clazzImplb")
      private BaseInterface baseInterfaceB;
    
      public BaseInterface getInstance(parameters which will decides what type of instance you want){
        // your logic to choose Instance A or Instance B
        return baseInterfaceA or baseInterfaceB
      }
    
    }
    

    구성 (뻔뻔하게 다른 의견에서 복사)

    @Configuration
    public class SpringConfig {
        @Bean(name="clazzImplA")
        public BaseInterface clazzImplA(){
            return new ClazzImplA();
        }
    
        @Bean(name="clazzImplB")
        public BaseInterface clazzImplB(){
            return new ClazzImplB();
        }
    }
    

    서비스 클래스

    @Service
    @SpringApplicationConfiguration(SpringConfig.class)
    public class AutowiredClazz {
        @Autowired
        private BaseInterfaceFactory factory;
    
        public void someMethod(){
           BaseInterface a = factory.getInstance(some parameters);
           // do whatever with instance a
        }
    }
    
  3. ==============================

    3.당신은 @Autowired를 사용하는 경우, Spring은 autowire하기 할 필드의 유형과 일치하는 빈을 검색합니다. 귀하의 경우에는 유형 BaseInterface 하나 이상의 콩이 있습니다. 즉 봄이 분명하게 일치하는 빈을 선택할 수 없습니다.

    당신은 @Autowired를 사용하는 경우, Spring은 autowire하기 할 필드의 유형과 일치하는 빈을 검색합니다. 귀하의 경우에는 유형 BaseInterface 하나 이상의 콩이 있습니다. 즉 봄이 분명하게 일치하는 빈을 선택할 수 없습니다.

    이러한 상황에서 명시 적으로 사용하거나 모호성을 해결해야 콩 봄을 상태로 다른 선택의 여지가 없다.

  4. ==============================

    4.이보다 쿨러 솔루션은 구현 자체가 그들이 적용 할 수 있는지 확인하기 위해 논리를 포함하도록하는 것입니다. 당신은 컬렉션으로 사용할 수있는 모든 구현을 주입하고 (즉, 당신이 필요하다면, 또는 그 이상)의 적용 것들을 하나를 찾을 그들을 반복 할 수 있습니다 :

    이보다 쿨러 솔루션은 구현 자체가 그들이 적용 할 수 있는지 확인하기 위해 논리를 포함하도록하는 것입니다. 당신은 컬렉션으로 사용할 수있는 모든 구현을 주입하고 (즉, 당신이 필요하다면, 또는 그 이상)의 적용 것들을 하나를 찾을 그들을 반복 할 수 있습니다 :

    public interface BaseInterface {
        boolean canHandle(Object parameter);
        Object doTheWork(Object parameter);
    }
    
    @Service
    public class SomeService {
    
        private final BaseInterface[] implementations;
    
        // Spring injects all beans implementing BaseInterface
        public MessageService(BaseInterface... implementations) {
            this.implementations = implementations;
        }
    
        public Object doSomething(Object parameter) {
            BaseInterface baseInterface = findBaseInterface(parameter);
            return baseInterface.doTheWork(parameter);
        }    
    
        private BaseInterface findBaseInterface(Object parameter) {
            return Arrays.stream(implementations)
                .findAny(i -> i.canHandle(parameter)
                .orElseThrow(new MyRuntimeException(String.format("Could not find BaseInterface to handle %s", parameter)));
        }
    }
    
  5. ==============================

    5.그것은 바로 인터페이스가 하나 개 이상의 클래스에 의해 구현되는 이러한 경우에 우리가 @Component를 사용하는 콩의 각 이름을 가지고 여기에 대답하고있다 (이름 = $ beanName에)

    그것은 바로 인터페이스가 하나 개 이상의 클래스에 의해 구현되는 이러한 경우에 우리가 @Component를 사용하는 콩의 각 이름을 가지고 여기에 대답하고있다 (이름 = $ beanName에)

    나는 그런 경우에 봄도지도에 같은 콩을 autowire하기 수있는 또 하나 개의 지점을 추가하고 싶습니다 :

    @Autowired
    Map<String,InterfaceName> interfaceMap;
    //this will generate beans and index them with beanName as key of map
    
  6. from https://stackoverflow.com/questions/37565186/spring-couldnt-autowired-there-is-more-than-one-bean-of-type by cc-by-sa and MIT license