@Autowired(2) - @Qualifier, @Primary
@Qualifier
만약 이러한 VO 클래스가 있다고 가정하자.
public class Fruit {
private String fruitName;
public void setFruitName(String name) {
fruitName = name;
}
public String getFruitName() {
return fruitName;
}
}
그리고 root-context.xml에 1개의 Fruit Bean을 생성했다고 가정하자.
<?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 https://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 이 부분! -->
<bean id = "fruit1" class = "com.test.bean.Fruit">
<property name="fruitName" value = "apple"/>
</bean>
</beans>
@Autowired 를 사용하여 사과 빈을 HomeController에 등록해보자.
@Controller
public class HomeController {
@Autowired
private Fruit fruit;
@RequestMapping("/")
public String home(Model model) {
model.addAttribute("fruit", fruit);
return "home";
}
}
결과 확인 - 잘 나온다! 이유는 was가 알아서 Fruit 타입의 bean을 찾아 대입해주기 때문이다.
그런데 만약 사과 뿐만 아니라 여러 과일이 등록되어있다면?
root-context.xml
<bean id="fruit1" class="com.test.bean.Fruit">
<property name="fruitName" value="apple" />
</bean>
<bean id="fruit2" class="com.test.bean.Fruit">
<property name="fruitName" value="banana" />
</bean>
<bean id="fruit3" class="com.test.bean.Fruit">
<property name="fruitName" value="orange" />
</bean>
다음과 같은 예외가 발생한다.
org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [com.test.bean.Fruit] is defined |
우리가 컴퓨터의 입장이라고 생각해본다면 너무나 당연한 결과다.
Fruit bean은 3개나 있는데, 어떤 bean을 택하라고 했는지 말은 안해주고 무작정 'Fruit bean과 연결해!' 라고만 지정했기 때문이다. 이때, '이 bean을 선택해!' 라는 의미로 @Qualifier 어노테이션을 사용할 수 있다.
@Controller
public class HomeController {
@Autowired
@Qualifier("fruit3") // id가 fruit3 인 bean과 연결해!
private Fruit fruit;
@RequestMapping("/")
public String home(Model model) {
model.addAttribute("fruit", fruit);
return "home";
}
}
결과 - 잘 나온다!
@Primary
@Primary 는 같은 타입의 빈이 여러 개 있을 때 @Quilifier를 지정해주지 않은 경우를 대비하여 '이 빈을 우선적으로 선택해!'라는 뜻으로 사용하는 어노테이션이다.
@Primary 를 자주 사용하는 클래스는 @Configuration 클래스다.
** @Configuration: root-context.xml, servlet-context.xml 등의 xml 파일로 Bean을 등록하던 행위를 어노테이션기반 java 클래스에서 수행하고자 할 때 해당 클래스를 @Configuration 으로 선언한다.
(spring 3.0 이하인 경우 pom.xml에 cglib 의존 주입을 해야 한다.)
<!-- https://mvnrepository.com/artifact/cglib/cglib -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.1</version>
</dependency>
다음은 @Configuration으로 지정된 FruiltConfig.java 이다.
@Configuration
public class FruitConfig {
@Bean
public Fruit orangeFruit() {
return new Fruit("orange");
}
@Bean
public Fruit bananaFruit() {
return new Fruit("banana");
}
@Bean
@Primary
public Fruit appleFruit() {
return new Fruit("apple");
}
}
Fruit Bean을 3개 생성하여 return하는 부분은 위에 작성한 root-context.xml의 동작과 같다.
이중 @Primary로 선언한 Bean이 우선적으로 Autowiring 되어 @Quilifier 애너테이션이 없는 @Autowired 멤버에 자동으로 대입된다.