Blog

[Spring]28 같은 타입의 Bean이 2개라면? 구현체가 2개이상인 Bean 등록할 때 주의점

Author
Summary
@Primary, @Qualifier로 지정 할 수 있으며, Qualifier가 우선순위가 높다.
Category
Study
Tags
Spring
Favorite
Memory Date
2023/09/03
Cross Reference Study
Related Media
Related Thought
Related Lessons
tag
날짜
작성자
진행상황
진행 전
태그구분
6 more properties
Food, Pizza, Chicken 예제를 통해 알아보기
Java에서 상속 및 추상화, 다형성 등을 공부하면서 자주 사용되는 Food 예시를 통해 사례를 살펴보고자 한다.
동일한 부모 클래스 또는 인터페이스가 추상화 되어 있고, 그것을 상속 받은 자손 클래스들이 실질적인 구현체를 가지고 있는데 여러개 자손일 경우, SpringBoot 환경에서는 그 상위 부모 타입의 객체로 생성한다면 어떤 자손을 선택하는가에 대한 문제이다.
Food.java
package com.sparta.springauth.food; public interface Food { void eat(); }
Java
복사
Chicken.java
package com.sparta.springauth.food; import org.springframework.stereotype.Component; @Component public class Chicken implements Food { @Override public void eat() { System.out.println("치킨을 먹습니다."); } }
Java
복사
Pizza.java
package com.sparta.springauth.food; import org.springframework.stereotype.Component; @Component public class Pizza implements Food { @Override public void eat() { System.out.println("피자를 먹습니다."); } }
Java
복사
이제 메인 메소드에서 음식을 생성해본다. 어떤것을 선택할까?
BeanTest.java
@SpringBootTest public class BeanTest { @Autowired Food food; }
Java
복사
@Autowired가 Bean을 주입하는 것에 실패했다는 오류 메시지가 나타난다. Food 객체를 생성하고자 하는데 그 전에 Chicken, Pizza중 어떤 것을 주입해야 되는지 지정해주지 않았기 때문이다.
Bean을 특정(지정)하는 3가지 방법
등록된 Bean이름 명시하기, 가장 기본적인 방법이다.
BeanTest.java
@SpringBootTest public class BeanTest { //[1] 명시적으로 Bean의 이름(Pizza 클래스의 빈이름은 pizza)을 적어준다. @Autowired Food chicken; @Autowired Food pizza; @Test @DisplayName("Bean 테스트") void test1(){ pizza.eat(); chicken.eat(); } }
Java
복사
@Primary 사용하기, Chicken 클래스에 @Primary를 추가한다면, 같은 타입의 Bean이 여러 개 있더라도 우선 @Primary가 설정된 Bean 객체를 주입
Chicken.java
@Component @Primary //[2]방법 -> @Primary가 추가되면, 2개 이상의 Bean이 등록되더라도 기본값으로 설정 된다. -> Food food; 사용가습 public class Chicken implements Food { //인터페이스의 구현체에 @Component를 등록하면 Bean으로 등록자체는 문제되지않는다. @Override public void eat() { System.out.println("치킨을 먹습니다."); } }
Java
복사
@Qualifier(beanname) 사용하기, Pizza 클래스에 @Qualifier("pizza") 를 추가하고, 주입하고자하는 필드에도 @Qualifier("pizza") 를 추가해주면 해당 Bean 객체가 주입
Pizza.java
@Component @Qualifier("pizza") //[3]방법 -> @Qualifier 추가되면, 대명사를 지정하는 것 처럼 Bean 명칭을 명시적으로 지정 하게 된다. public class Pizza implements Food { //인터페이스의 구현체에 @Component를 등록하면 Bean으로 등록자체는 문제되지않는다. @Override public void eat() { System.out.println("피자를 먹습니다."); } }
Java
복사
BeanTest.java
@SpringBootTest public class BeanTest { //[3] 구현체가 2개 이상 일 때, 둘 중 하나 class에 @Qualifier("chicken")을 작성하면 chicken이라고 명시적으로 구분할 수 있도록 등록 할 수 있다. // 해당 @Qualifier("pizza") 어노테이션은 Bean을 초기화하는 부분에서도 @Qualifier("pizza")를 동일하게 작성해 주어야 한다. @Autowired @Qualifier("pizza") //<- 이 명칭은 Bean 명칭과 정확히 일치해야 찾을 수 있다. Food food; @Test @DisplayName("@Qualifier() 테스트") void test3(){ food.eat(); }
Java
복사