No qualifying bean of type, 생성자 주입 방식 @Resource(name) 에러

GilLog·2020년 11월 7일
0

에러

목록 보기
5/17
 2020 5:34:36 오후 org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Allocate exception for servlet [DispatcherServlet]
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [kr.happyjob.chainmaker.basic.repo.UserDAO] is defined: expected single matching bean but found 2: UserDAOEventImpl,UserDAOImpl
	at org.springframework.beans.factory.config.DependencyDescriptor.resolveNotUnique(DependencyDescriptor.java:172)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1059)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1018)
	at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:834)
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741)

다음과 같은 에러가 발생 했다.

현재 상황은

Controller > Service > Repository로 가는 중에

@Autowired 방식이 아닌 @Resource Annotation을 통한 DI를 테스트 해보던 중에 발생했다.

  • BasicController

@Controller
@RequestMapping(value = "/basic")
public class BasicController {
	
	private static final Logger logger = LoggerFactory.getLogger(BasicController.class);
	
	@Resource(name="UserServiceImpl")
	private UserService userService;
	
	// MVC 기본 구조
	@RequestMapping(value = "/", method = RequestMethod.GET)
	public String mvcBasic(Model model) {
		logger.info("GilContorller.mvcBasic() 실행 중");
	
		String anyLetterCanBeHere = "테스트 중 입니다.";
		
		String loginID = "admin";
		
		UserDTO userDTO = userService.getUserInfoByLoginID(loginID);
		
		String name = userDTO.getName();

		model.addAttribute("message", anyLetterCanBeHere);
		model.addAttribute("loginID", loginID);
		model.addAttribute("name", name);
		
		model.addAttribute("userDTO", userDTO);
		
		return "basic/mvc_basic";
	}
	
	// Vue 관련 기본 예제
	@RequestMapping(value = "/vue", method = RequestMethod.GET)
	public String vueBasic(){

		logger.info("GilContorller.vueBasic() 실행 중");
		
		return "basic/vue_basic";
	}
	
	// Vue dataTable 예제
	@RequestMapping(value = "/datatable", method = RequestMethod.GET)
	public String vueDataTable(){

		logger.info("GilContorller.vueDataTable() 실행 중");
		
		return "basic/vue_datatable";
	}
}
  • UserServiceImpl
@Service("UserServiceImpl")
@Transactional
@AllArgsConstructor
public class UserServiceImpl implements UserService {

	@Resource(name="UserDAOEventImpl")
	UserDAO userDAO;
	
	@Override
	public UserDTO getUserInfoByLoginID(String loginID) {
		
		UserVO userVO = userDAO.getUserInfoByLoginID(loginID);
		
		UserDTO userDTO = new UserDTO(userVO);
		
		return userDTO;
	}

}
  • UserDAOEventImpl
@Repository("UserDAOEventImpl")
@AllArgsConstructor
public class UserDAOEventImpl implements UserDAO{

	private SqlSession sql;
	
	@Override
	public UserVO getUserInfoByLoginID(String loginID) {
		return sql.selectOne("userMapper.getUserInfoByLoginID", "babo");
	}
    }
  • UserDAOImpl

@Repository("UserDAOImpl")
@AllArgsConstructor
public class UserDAOImpl implements UserDAO{

	private SqlSession sql;
	
	@Override
	public UserVO getUserInfoByLoginID(String loginID) {
		return sql.selectOne("userMapper.getUserInfoByLoginID", loginID);
	}

}

각각의 Stereotype Annotation에 name을 배당해주었는데도

No qualifying bean of type [kr.happyjob.chainmaker.basic.repo.UserDAO] is defined: 
expected single matching bean but found 2: UserDAOEventImpl,UserDAOImpl

UserServiceImpl에서 UserDAO에 UserDAOEventImpl bean name으로 매핑 시켜주는 부분에서 문제가 발생하는걸 확인했다.

  • 문제 부분
@Service("UserServiceImpl")
@Transactional
@AllArgsConstructor
public class UserServiceImpl implements UserService {

	@Resource(name="UserDAOEventImpl")
	UserDAO userDAO;
	
	@Override
	public UserDTO getUserInfoByLoginID(String loginID) {
		
		UserVO userVO = userDAO.getUserInfoByLoginID(loginID);
		
		UserDTO userDTO = new UserDTO(userVO);
		
		return userDTO;
	}

}

결국 여러가지 시도를 벌이다가

@AllArgsConstructor를 지우면서 해결 할 수 있었다.

  • 해결 부분
@Service("UserServiceImpl")
@Transactional
public class UserServiceImpl implements UserService {

	@Resource(name="UserDAOEventImpl")
	UserDAO userDAO;
	
	@Override
	public UserDTO getUserInfoByLoginID(String loginID) {
		
		UserVO userVO = userDAO.getUserInfoByLoginID(loginID);
		
		UserDTO userDTO = new UserDTO(userVO);
		
		return userDTO;
	}

}

아마도 원인은 @AllArgsConstructor는 생성 당시에 필드 값을 파라미터로 받은 생성자를 추가해주는 Lombok Annotation인데 Container에서 streotype component들을 bean 생성할때 각각의 UserDAOImpl, UserDAOEventImpl에서 @Repositroy에 선언한 bean name을 @Resource 부분에서 매핑을 못시켜줘서 발생한 오류인것 같다.

더 자세히 알아봐야겠다.

어쨋든 해결 완료

profile
🚀 기록보단 길록을 20.10 ~ 22.02 ⭐ Move To : https://gil-log.github.io/

0개의 댓글