LUMI_dev

Bean - #2.같은 타입의 Bean이 2개라면?_@Primary, @Qualifier 본문

스파르타 코딩 클럽 | 자바 심화 과정/Spring Master (숙련 주차)

Bean - #2.같은 타입의 Bean이 2개라면?_@Primary, @Qualifier

luminous_dev 2025. 2. 4. 13:13
더보기




Food(Interface)

package com.sparta.springauth.food;

public interface Food {
    void eat();
}

 

Chicken (class)

package com.sparta.springauth.food;

import org.springframework.stereotype.Component;

@Component
public class Chicken implements Food {
    @Override
    public void eat() {
        System.out.println("치킨을 먹습니다.");
    }
}

 

Pizza(class)

package com.sparta.springauth.food;

import org.springframework.stereotype.Component;

@Component
public class Pizza implements Food {
    @Override
    public void eat() {
        System.out.println("피자를 먹습니다.");
    }
}

 

 

 

 


커피콩 모양 누르기 > Spring 뷰에서 선택 누르기

 

인터페이스를 구현하는 Class(ex. Food를 구현하는 Pizza와 Chicken)를 만든 다음

Bean으로 등록하면 (ex.@Component,Service,Repository..등) 

 

인터페이스에서 저렇게 커피콩 모양으로 뜸

= Bean으로 food란 interface 타입으로 Bean이 등록되었다라는 뜻 


BeanTest 만들어주기

 

 

인터페이스도 @Autowired 가능함

이때 아래와 같이 Autowired하려고 하면 빨간 불 뜸

 

원인) Food타입 Bean객체가 하나 이상 생겨서 발생 /Pizza,Chicken 중 어떤 거 주입할 거야?

 

해결방법)

1. 등록이 된 Bean의 이름을 명시

기본적으로 @Autowired는 Bean 타입으로 DI를 지원하는데 

연결이 되지 않을 경우 Bean의 이름으로 찾음 (ex. chicken,pizza)

 

BeanTest.java 

package com.sparta.springauth;

import com.sparta.springauth.food.Food;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest //이걸 걸어야지 Bean 주입 받아 오는 것, DI 사용 가능
public class BeanTest {


    @Autowired
    Food pizza;
    @Autowired
    Food chicken;


    @Test
    @DisplayName("테스트")
    void test1() {
        pizza.eat();
        chicken.eat();
    }
}

 

결과

 

2. 인터페이스 구현받은 클래스 중 우선적으로 가져올 클래스에 @Primary 붙이기

@Primary //같은 타입의 Bean이 여러개 있어도 우선적으로 이 Primary가 적용되어 있는 Bean 객체를 주입해줌

 

BeanTest.java

package com.sparta.springauth;

import com.sparta.springauth.food.Food;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest //이걸 걸어야지 Bean 주입 받아 오는 것, DI 사용 가능
public class BeanTest {

    //interface도 @Autowired 가능한가요? 가능
    @Autowired
    Food food;

    @Test
    @DisplayName("테스트")
    void test1() {
    package com.sparta.springauth;

import com.sparta.springauth.food.Food;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest //이걸 걸어야지 Bean 주입 받아 오는 것, DI 사용 가능
public class BeanTest {

    //interface도 @Autowired 가능한가요? 가능
    @Autowired
    Food food;


    @Test
    @DisplayName("테스트")
    void test1() {
        food.eat();
    }
}

 

 

Chicken.java 

package com.sparta.springauth.food;

import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;

@Component
@Primary //같은 타입의 Bean이 여러개 있어도 우선적으로 이 Primary가 적용되어 있는 Bean 객체를 주입해줌
public class Chicken implements Food {
    @Override
    public void eat() {
        System.out.println("치킨을 먹습니다.");
    }
}

 

 

3. @Qualifier("pizza")

 

pizza.java

package com.sparta.springauth.food;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

@Component
@Qualifier("pizza")
public class Pizza implements Food {
    @Override
    public void eat() {
        System.out.println("피자를 먹습니다.");
    }
}

 

BeanTest.java에도 @Qualifier

package com.sparta.springauth;

import com.sparta.springauth.food.Food;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest //이걸 걸어야지 Bean 주입 받아 오는 것, DI 사용 가능
public class BeanTest {

    //interface도 @Autowired 가능한가요? 가능
    @Autowired
    @Qualifier("pizza")
    Food food;

    @Test
    @DisplayName("테스트")
    void test1() {
        food.eat();
    }
}

Primary와 Qualifier 중 어떤 것의 우선순위가 높을까?

> Qualifier

 

범용적으로 사용되는 Bean 객체에는 Primary를

지역적으로 사용되는 Bean 객체에는 Qualifier  사용


Spring의 우선 순위

큰 범위 우선순위가 더 낮음 (Primary) / 작은 범위 우선순위가더  높음 (Qualifier)