프로젝트 내 개발 진행 중 발생한 에러인데 아직 명확한 해결책은 나지 않았지만 우선 정리해 둔다.


 @Autowired

  private GenericDao<Map<String, Object>> dao;

 @Autowired

  private SampleListDao<Map<String, Object>> sampleListDao;



우선 소스코드에 위와 같이 선언하여 service 구현체에 dao를 가져다 쓰려했다. 서버를 구동시키자 아래와 같은 에러가 떨어졌다.


1) 에러 메세지


Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [xxx.orm.mybatis.GenericDao] is defined: expected single matching bean but found 2: sampleListDao,genericDao

at org.springframework.beans.factory.config.DependencyDescriptor.resolveNotUnique(DependencyDescriptor.java:172)



 - 확인해보니, 찾으려는 bean에대해 한 개 이상의 bean이 존재하여 발생하는 에러였다. 

 - 에러에 대해 알아보기 위해 GenericDao와 SampleListDao 소스에 각각 들어가 살펴보았다.

   GenericDao는 SqlSessionDaoSupport를 extends 한 class 였고, SampleListDao는 그 GenericDao를 extends하고 있는 class였다. (내가 그렇게 만듬...ㅎ)



2) 원인


 - @Autowired로 주입하고 있기 때문에 Type을 검색하여 연결하는데, SampleListDao와 GenericDao의 생성 type이 결국 조상 class인 

   SqlSessionDaoSupport로 type이 같기 때문에 @Autowired가 누굴 찾아 주입해야하는지 명확히 알 수 없기 때문이다.

   이러한 경우 name 을 주어 어떤 bean을 주입할 지 결정해주곤 한다.


- 그래서 아, name 으로 구분하면 되겠네 하고 name을 주어 @Resource로 빈 주입을 시도했다.

- 하지만 예상과 다르게 계속 같은 에러가 발생했다....충격 

  음 아직 명확한 답은 모르겠으나, 'extends' 가 문제인 것 같다. SampleListDao가  SqlSessionDaoSupport를 extends 하여 맨위와 같이 선언하면

  문제없이 돌아간다. (참고로 SqlSessionDaoSupport는 abstract class)


- SqlSessionDaoSupport를 extends 하면 name 기반으로도 주입이 잘 된다. 



3) 해결


    - 명확한 해결방법은 좀 더 연구해보아야 할 것 같다... 자료도 더 찾아보고

    

    

4) 보충 자료


먼저 @Autowired 와 @Resource.


@Autowired 와 @Resource는 모두 의존관계를 자동으로 주입하기 위한 설정이다. 

비슷한 기능을 하지만 약간의 차이가 존재하는데, 이 둘의 차이점은 아래와 같다.



 @Autowired

 @Resource

 공통점

 의존관계를 자동으로 주입하기 위한 설정

 차이점1: 지원

 Spring Framework

 Java

차이점2: 검색 

bean의 Type으로 검색하여 의존성 주입 

bean의 Name으로 검색하여 의존성 주입 

 옵션

 @Autowired는 타입을 이용해서 자동적으로 값을 설정하기때문에 해당 타입의 빈 객체가 존재하지 않거나 또는 2개이상 존재할 경우 빈객체를 생성할때 예외를 발생시킨다.이 경우를 대비하여  @Autowired(required=false) 옵션을 설정할 수 있다. 해당 옵션을 설정하면 연결할 bean을 찾지 못해도 예외를 발생시키지 않는다.

 name 속성을 이용하여 명시적으로 bean name을 줄 수 있다.

 단점

 type으로 검색하여 연결하기 때문에 같은 타입이 2개 이상 존재하는 경우, 예외가 발생한다.

  --> 보완: @Qualifier

        (동일한 type의 bean 객체들 중 name을 사용하여 특정 bean

        을 연결하도록 설정 가능)

 


 - @Autowired는 spring에서 제공하는 annotation이기 때문에 spring을 쓰지 않고 다른 framework를 쓰는 경우

   더이상 사용할 수 없다는 단점이 있다. 반면, @Resource는 JAVA에서 제공하는 annotation이기 때문에

   framework에 관계없이 계속 사용할 수 있다는 장점이 있다.


 - @Autowired는 생성 Type으로 연결하지만, @Resource는 name으로 연결하기 때문에 주입하려는 bean에 name을 설정해주어야 한다.

   예를 들면,

 

@Service("sampleService")

public class SampleServiceImpl implements SampleService { 


 ...


@Resource(name="sampleService")

private SampleService sampleService;


 - 위의 예제와 같이 주입하려는 bean (@Service)에 name(sampleService)을 설정해주고 해당 bean을 가져다 쓰려는 곳에서

  @Resource(name="sampleService") 로 검색하여 찾아 연결한다. 



 - @Qualifier는 @Autowired를 보완하기 위해 나온 annotation으로, 동일한 type의 빈 객체들 중 name을 기반으로 특정 빈을 사용할 수 있도록 

   설정해준다.


 @Autowired

 @Qualifier("genericDao")

 private GenericDao<Map<String, Object>> dao;

 @Autowired

 @Qualifier("sampleListDao")

 private SampleListDao<Map<String, Object>> sampleListDao;  




__________________________________________________________________________________________________________________________________________________________

** 본 포스팅에 대해 수정해야할 부분이나 추가 의견 등이 있으신 분들은 댓글 달아주세요. 언제나 환영입니다 :) 

** 본 포스팅을 reference 자료로 참고하실 분들은 출처를 꼭 밝혀주시기 바랍니다.



+ Recent posts