도서관을 이용한느 사용자가 도서를 대출하는 기능을 구현한다.
패키지와 클래스 생성하기
실습에 필요한 패키지와 클래스를 만들고 데이터베이스에 도서 대출 테이블(tbl_rental_book)도 생성해본다.
com.office.library.book.user 패키지와 클래스를 다음과 같이 만든다.
※ BookVo는 com.office.library.book 패키지에 관리자와 사용자 공용으로 사용하고 있어 별도로 생성하지 않는다.
빈 충돌 에러
앞에서 생성한 클래스들을 스프링 IoC 컨테이너에 빈으로 등록하기 위한 설정을 한다.
package com.office.library.book.user;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/book/user")
public class BookController {
}
package com.office.library.book.user;
import org.springframework.stereotype.Service;
@Service
public class BookService {
}
package com.office.library.book.user;
import org.springframework.stereotype.Component;
@Component
public class BookDao {
}
컨트롤러, 서비스, DAO를 모두 만들고 프로젝트를 실행하면 다음과 같은 에러가 발생하는 것을 확인할 수 있다.
이는 ConflictingBeanDefinitionException 에러로, BookController 빈이 동일한 이름으로 이미 존재해서 충돌이 발생하는 것이다.
빈은 스프링 IoC 컨테이너에 등록될 때 클래스 이름의 첫 글자를 소문자로 변경해서 빈을 구분하는 이름(ID, 아이디)으로 사용한다. 그런데 이번에 만든 BookController의 경우 com.office.library.book.admin 패키지의 BookController와 동일한 이름(bookController)이기 때문에 충돌이 발생하게 된다.
해결 방법 1: 빈의 아이디 다르게 설정하기
빈의 아이디를 다르게 하면 해결할 수 있다. com.office.library.book.admin과 com.office.library.book.user 패키지의 BookController의 @Controller를 다음과 같이 수정한다.
■ book.admin의 BookController.java
//@Controller
@Controller("admin.BookController")
@RequestMapping("/book/admin")
public class BookController {...}
■ book.user의 BookController.java
//@Controller
@Controller("user.BookController")
@RequestMapping("/book/user")
public class BookController {...}
이렇게 하면 book.admin과 book.user 패키지의 BookController는 서로 다른 아이디를 가지게 되어 출동을 피할 수 있다.
서비스와 DAO 역시 동일한 아이디를 갖지 않도록 수정해야 한다.
■ book.admin의 BookService.java
//@Service
@Service("admin.BookService")
public class BookService {...}
■ book.user의 BookService.java
//@Service
@Service("user.BookService")
public class BookService {...}
■ book.admin의 BookDao.java
//@Component
@Component("admin.BookDao")
public class BookDao {...}
■ book.user의 BookDao.java
//@Component
@Component("user.BookDao")
public class BookDao {...}
이제 프로젝트를 다시 실행하면 정상적으로 실행되는 것을 확인할 수 있다.
해결 방법 2: BeanNameGenerator 사용하기
스프링에는 BeanNameGenerator 인터페이스가 있다. 이 BeanNameGenerator를 이용하면 동일한 이름의 클래스를 다르게 빈으로 등록할 수 있다.
① 우선 com.office.library.config 패키지를 생성한다.
② com.office.library.config 패키지에 LibraryBeanNameGenerator.java 클래스를 생성한다.
③ BeanNameGenerator 인터페이스를 추가하기 위해서 Interfaces의 <Add> 버튼을 클릭한다.
④ [Implemented Interfaces Selection] 창이 나오면 BeanNameGenerator를 입력하고 <OK>을 클릭한다.
![]() |
![]() |
![]() |
LibraryBeanNameGenerator.java를 다음과 같이 코딩한다.
package com.office.library.config;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanNameGenerator;
public class LibraryBeanNameGenerator implements BeanNameGenerator {
@Override
public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
return definition.getBeanClassName();
}
}
이제 빈의 아이디를 생성하는 LibraryBeanNameGenerator를 만들었으므로 스프링 컨테이너가 생성될 때 LibraryBeanNameGenerator를 이용하게 하면 된다. servlet-context.xml의 <context:component-scan>을 다음과 같이 수정한다.
● before
<context:component-scan base-package="com.office.library" />
● after
<context:component-scan base-package="com.office.library"
name-generator="com.office.library.config.LibraryBeanNameGenerator" />
이제 다시 이전상태로 복원하고 프로젝트를 실행하여 정상적으로 수행되는지 확인해본다.
빈이 생성될 때 아이디가 구분된 것을 확인할 수 있다.
'Spring & Springboot > 올인원 스프링 프레임워크' 카테고리의 다른 글
전자 도서관 프로젝트 - 도서 대출 기능 구현 (0) | 2023.12.03 |
---|---|
전자 도서관 프로젝트 - 도서 검색 기능 구현 (0) | 2023.12.03 |
전자 도서관 프로젝트 - 비밀번호 분실 처리 구현 (0) | 2023.12.02 |
전자 도서관 프로젝트 - 로그인 및 로그아웃 구현 (0) | 2023.12.02 |
전자 도서관 프로젝트 - 회원가입 구현 (0) | 2023.12.02 |