3. @Qualifier로 주입할 객체를 지정하기
@Autowired는 프로퍼티에 주입할 수 있는 의존 객체가 여러 개 있을 경우 오류를 발생시킨다. 즉 같은 타입의 객체가 여러 개 있으면 그 중에서 어떤 객체를 주입해야 할지 알 수 없기 때문이다. 이 경우 어노테이션 @Qualifier를 사용하면 손쉽게 해결할 수 있다. @Qualifier는 빈의 이름(또는 아이디)으로 의존 객체를 지정할 수 있다.
이 어노테이션을 사용하려면 빈의 후 처리기(bean post processor)가 필요하다. 이런식으로 하다보면 어노테이션을 사용할 때마다 그 어노테이션을 처리할 객체를 등록해야 하는 불편함이 발생한다. 이런 불편함을 해소하기 위해 스프링에서는 어노테이션 처리와 관련된 빈(bean post processor)을 한꺼번에 등록할 수 있는 방법을 제공한다. 다음과 같이 간단히 태그를 선언하면 된다.
<context:annotation-config/>
실습을 통해 @Qualifier의 사용법을 익혀 본다.
- 실습 패키지 생성
exam 패키지 아래에 test19 패키지를 생성한다. test18 패키지의 모든 파일을 복사해온다.
- beans.xml 빈 설정 파일
exam/test19/beans.xml 파일을 열고 다음과 같이 편집한다.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:context="http://www.springframework.org/schema/context"
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="hyundaiEngine" class="exam.test19.Engine">
<constructor-arg value="Hyundai"/>
</bean>
<bean id="kiaEngine" class="exam.test19.Engine">
<constructor-arg value="Kia"/>
</bean>
<bean id="car1" class="exam.test19.Car">
<property name="model" value="Sonata"/>
</bean>
</beans>
xmlns:context="http://www.springframework.org/schema/context"
annotation-config 태그는 context 네임스페이스에 들어 있다. 따라서 이 태그를 사용하기 전에 먼저 네임스페이스를 선언해야 한다.
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 네임스페이스의 태그 규칙을 정의한 XML 스키마 파일을 지정한다.
<context:annotation-config/>
context 네임스페이스 준비가 끝났으면 annotation-config 태그를 선언한다. 이 태그를 선언하면 어노테이션 처리를 담당하는 다음의 빈들이 자동 등록되는데, 빈의 후 처리기 - 주요 어노테이션 처리기를 정리한 표이다.
어노테이션 | 빈의 후 처리기 |
@Autowired, @Value, @Inject (JSR-330) | AutowiredAnnotationBeanPostProcessor |
JSR-250 어노테이션(javax.annotation.*) | CommonAnnotationBeanPostProcessor |
@PersistenceUnit, @PersistenceContext | PersistenceAnnotationBeanPostProcessor |
@Required | RequiredAnnotationBeanPostProcessor |
<bean id="hyundaiEngine" class="exam.test19.Engine">
<constructor-arg value="Hyundai"/>
</bean>
<bean id="kiaEngine" class="exam.test19.Engine">
<constructor-arg value="Kia"/>
</bean>
Car 객체에서 사용할 Engine 객체를 두 개 준비한다.
<bean id="car1" class="exam.test19.Car">
<property name="model" value="Sonata"/>
</bean>
Car 객체를 준비한다. engine 프로퍼티의 값은 설정하지 않는다. @Autowired로 선언되었기 때문에 스프링 IoC 컨테이너가 자동으로 Engine 객체를 주입할 것이다.
- @Qualifier를 사용하여 의존 객체 지정
어노테이션 @Qualifier를 사용하여 engine 프로퍼티에 들어갈 객체를 지정해 본다.
exam.test19.Car 클래스를 열고 setEngine() 메서드를 다음과 같이 편집한다.
package exam.test19;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
public class Car {
...
@Autowired(required=false)
@Qualifier("kiaEngine")
public void setEngine(Engine engine) {
this.engine = engine;
}
...
}
@Autowired(required=false)
@Qualifier("kiaEngine")
engine 프로퍼티(setEngine()) 앞에 @Qualifier 선언을 추가한다. 이 어노테이션에 들어가는 값은 beans.xml에 선언된 엔진 객체 중에서 'kiaEngine'을 가리키는 이름이다. 빈 컨테이너는 engine 프로퍼티의 값으로 해당 이름을 갖는 객체를 찾아 주입한다.
- 빈 컨테이너 테스트
@Qualifier에 지정된 대로 engine 프로퍼티에 해당 객체가 주입되었는지 확인해 본다. exam.test19.Test 클래스를 다음과 같이 편집한다. beans.xml 파일의 폴더 이름(test19)을 제외하고 나머지 코드는 이전 실습과 같다.
package exam.test19;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
//IoC 컨테이너 준비하여 빈 생성
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("exam/test19/beans.xml");
Car car1 = (Car)ctx.getBean("car1");
System.out.println(car1.getEngine());
}
}
Test 클래스를 실행해 보면 다음의 결과를 얻을 수 있다. @Qualifier에 지정한 대로 해당 의존 객체(kiaEngine)가 정확히 주입되었음을 알 수 있다(그림 1).
4. @Autowired + @Qualifier = @Resource
JSR-250 명세에 정의된 @Resource를 사용하면 더 간단히 특정 의존 객체를 지정할 수 있다. 이름으로 의존 객체를 지정할 경우 이 어노테이션을 사용할 것을 권장한다. 단, @Autowired는 required 속성을 사용하여 프로퍼티 값의 필수 여부를 지정할 수 있지만 @Resource에는 그런 기능이 없으므로 @Resource는 무조건 필수 입력이다. 해당 프로퍼티에 주입할 의존 객체가 없으면 오류가 발생하므로 의존 객체 주입을 선택 사항으로 만들고 싶다면 @Autowired를 사용한다.
- 실습 패키지 생성
exam 패키지 아래에 test20 패키지를 생성한다. test19 패키지의 모든 파일을 복사해온다.
- @Resource를 사용하여 의존 객체 지정
@Autowired와 @Qualifier 대신 @Resource를 사용하여 의존 객체를 지정해 본다.
exam.test20.Car 클래스를 열고 setEngine() 메서드를 다음과 같이 편집한다.
package exam.test20;
import java.util.Map;
import javax.annotation.Resource;
public class Car {
...
@Resource(name="kiaEngine")
public void setEngine(Engine engine) {
this.engine = engine;
}
...
}
@Resource(name="kiaEngine")
@Autowired와 @Qualifier 선언을 제거한다. 대신 @Resource를 선언하고 name 속성에 주입하고자 하는 의존 객체의 이름을 지정한다.
- beans.xml 빈 설정 파일
exam/test20/beans.xml 파일을 열고 다음과 같이 편집한다. 이전 실습 소스와 비교해 특별히 바꿀 것은 없고, 각 클래스의 패키지 이름만 test19에서 test20으로 변경한다.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:context="http://www.springframework.org/schema/context"
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="hyundaiEngine" class="exam.test20.Engine">
<constructor-arg value="Hyundai"/>
</bean>
<bean id="kiaEngine" class="exam.test20.Engine">
<constructor-arg value="Kia"/>
</bean>
<bean id="car1" class="exam.test20.Car">
<property name="model" value="Sonata"/>
</bean>
</beans>
- 빈 컨테이너 테스트
@Resource가 제대로 동작하는지 확인해 본다. exam.test20.Test 클래스를 다음과 같이 편집한다. beans.xml 파일의 폴더 이름(test20)을 제외하고 나머지 코드는 이전 실습과 같다.
package exam.test20;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
//IoC 컨테이너 준비하여 빈 생성
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("exam/test20/beans.xml");
Car car1 = (Car)ctx.getBean("car1");
System.out.println(car1.getEngine());
}
}
실행 결과는 이전 실습과 같다. @Resource에 설정한 대로 해당 의존 객체(kiaEngine)가 정확히 주입되었음을 알 수 있다(그림 2).
참고도서 : https://freelec.co.kr/book/1674/
[열혈강의] 자바 웹 개발 워크북
[열혈강의] 자바 웹 개발 워크북
freelec.co.kr
'교재 실습 > 자바 웹 개발 워크북' 카테고리의 다른 글
150. Gradle 적용 (0) | 2022.11.13 |
---|---|
149. 빈 자동 등록 (1) | 2022.11.11 |
147. 어노테이션을 이용한 의존 객체 자동 주입 (1) (0) | 2022.11.09 |
146. 날짜 값 주입 (2) (0) | 2022.11.08 |
145. 날짜 값 주입 (1) (1) | 2022.11.07 |
댓글