Spring Framework

@Autowired(2) - @Qualifier, @Primary

issell 2019. 5. 26. 20:17

@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";
	}
}

 

결과 - 잘 나온다!

(fruit3 은 orange다.)

 


@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 멤버에 자동으로 대입된다.