의존 객체 자동 주입
의존객체 자동 주입은 스프링 설정 파일에서 의존 객체를 주입할 때 <constructor-org> 또는 <property> 태그로 의존 대상 객체를 명시하지 않아도 스프링 컨테이너가 자동으로 필요한 의존 대상 객체를 찾아서 의존 대상 객체가 필요한 객체에 주입해 주는 기능이다. 구현 방법은 @Autowired와 @Resource 어노테이션을 이용해서 쉽게 구현할 수 있다.
1. @Autowired
@Autowired는 주입하려고 하는 객체의 타입이 일치하는 객체를 자동으로 주입한다.
· @Autowired 사용 전
public class BookService {
private BookRepository bookRepository;
public BookService(BookRepository bookRepository){
this.bookRepository = bookRepository;
}
}
BookService Class는 생성자로 BookRepository를 전달받고 인스턴스 변수에 할당하는 코드를 가지고 있다.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="bookRepository" class="com.kim.service.bookRepository" />
<bean id="bookService" class="com.kim.service.BookService">
<constructor-arg ref="bookRepository" />
</bean>
</beans>
BookService에 BookRepository를 주입하기 위해서 XML 파일에 다음과 같이 <constructor-arg> 설정을 해줘야 한다.
· @Autowired 사용 시
public class BookService {
private BookRepository bookRepository;
@Autowired
public BookService(BookRepository bookRepository){
this.bookRepository = bookRepository;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" <!--추가-->
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context <!--추가-->
http://www.springframework.org/schema/context/spring-context.xsd"> <!--추가-->
<context:annotation-config /> <!--추가-->
<bean id="bookRepository" class="com.kim.service.BookRepository" />
<bean id="bookService" class="com.kim.service.BookService" />
</beans>
객체의 의존성을 가지는 부분에 @Autowired를 사용하고, xml파일에 네임스페이스와 스키마만 추가해주면 향후엔 계속해서 <constructor-arg> 설정 없이 쉽게 의존성을 주입받을 수 있다.
그러나 @Autowired는 생성자 위에만 명시할 수 있는 것은 아니다, 프로퍼티와 메서드 위에도 명시가 가능한데 단, 이때는 반드시 디폴트 생성자를 명시해줘야 한다.
public class BookService {
@Autowired
private BookRepository bookRepository;
public BookService(){ /* 디폴트 생성자 추가 */
}
public BookService(BookRepository bookRepository){
this.bookRepository = bookRepository;
}
@Autowired
public void setBook(Book book){
this.book = book;
}
}
2. @Resource
@Resource는 주입하려고 하는 객체의 이름이 일치하는 객체를 자동으로 주입한다. @Autowired는 생성자, 프로퍼티, 메소드에 다 사용할 수 있는 반면, @Resource는 프로퍼티와 메소드에만 사용이 가능하다. 이 역시도 디폴트 생성자가 필요하다.
public class BookService {
@Resource
private BookRepository bookRepository;
public BookService(){ /* 디폴트 생성자 추가 */
}
public BookService(BookRepository bookRepository){
this.bookRepository = bookRepository;
}
@Resource
public void setBook(Book book){
this.book = book;
}
}
즉, @Autowired는 "BookRepository bookRepository" 구문에서 타입인 BookRepository를 찾아서 들어가고, @Resource는 이름인 bookRepository를 찾는다.
의존객체 선택
다수의 빈(Bean) 객체 중 의존 객체의 대상이 되는 객체를 선택하는 방법에 대해서 알아보자. 어노테이션으로만 자동적으로 객체를 주입할 경우 컨테이너에서 주입할 대상이 여러 개여서 의존성을 주입하지 못하는 경우가 발생할 수 있다. 즉,
동일한 객체가 2개 이상인 경우 스프링 컨테이너는 자동 주입 대상 객체를 판단하지 못해서 Exception을 발생시킨다.
1. @Autowired - @Qualifier
@Autowired
private Book book;
<bean id ="book1" class ="com.kim.service.Book" />
<bean id ="book2" class ="com.kim.service.Book" />
<bean id ="book3" class ="com.kim.service.Book" />
판단하지 못하는 상황은 위와 같은 경우인데, 이 경우 @Qualifier 어노테이션을 써서 하나의 의존객체를 선택하여 객체 간 선택적 충돌이 발생하지 않게 할 수 있다.
@Autowired
@Qualifier("usedBook")
private Book book;
<bean id ="book1" class ="com.kim.service.Book" >
<qualifier value ="usedBook" />
</bean>
<bean id ="book2" class ="com.kim.service.Book" />
<bean id ="book3" class ="com.kim.service.Book" />
2. @Inject - @Named
@Inject는 자동주입을 하려는 경우 객체가 생성되지 않아서 주입을 하지 못하는 경우에 사용한다.
@Autowired // Exception 발생
private Book book;
<!-- <bean id ="book" class ="com.kim.service.Book" /> -->
물론 @Autowired에 "@Autowired(required = false)"라고 바꿔주면 Exception 발생하는 것을 막을 수는 있지만, 잘 쓰지 않는다. 그래서 이와 똑같은 역할을 하는 @Inject를 사용해볼 것이다. 방법은 @Autowired와 거의 똑같다.
@Inject
@Named(value="book1")
private Book book;
<bean id ="book1" class ="com.kim.service.Book" />
<bean id ="book2" class ="com.kim.service.Book" />
<bean id ="book3" class ="com.kim.service.Book" />
위에서 사용한 @Named는 @Autowired에서 @Qualifier과 같은 역할을 하며, 이를 사용할때는 따로 빈(Bean) 설정에 추가할 필요가 없다. 훨씬 간편하게 Exception을 피할 수 있다.
@Autowired와 @Inject 중 @Autowired가 실무에서 가장 많이 쓰이지만, 적절히 활용하면 좋은 코드가 나올 수 있을 것이다.
'Web[웹] > Spring Framework' 카테고리의 다른 글
[Spring] MVC 웹 프로그래밍 설계 모델 (With. STS) (0) | 2019.11.22 |
---|---|
[Spring] 어노테이션을 이용한 스프링 설정 (0) | 2019.11.21 |
[Spring] 스프링 설정 파일 분리와 빈 스코프(Bean Scope) (0) | 2019.11.20 |
[Spring] 의존객체와 DI(Dependency Injection) (0) | 2019.11.19 |
[Spring] 따라해보는 스프링 프로젝트 생성 (0) | 2019.11.18 |