슬기로운 개발생활

[Spring] 동일 타입의 빈(Bean)이 여러 개일 때 구분하여 주입하기

by coco3o
반응형

스프링 컨테이너에 빈을 등록하면 스프링 컨테이너가 알아서 의존관계를 맺어준다.
그런데 만약 동일 타입의 빈이 여러 개 존재한다면 (하나의 인터페이스에 여러 개의 구현 클래스가 있다면)
스프링에서 어떻게 구분해서 빈을 주입할까?

예시 코드

public interface JdbcRepository {}

@Repository
public class OracleRepository implements JdbcRepository {}

@Repository
public class MySQLRepository implements JdbcRepository {}
@Service
public class JdbcService {
    @Autowired
    private JdbcRepository jdbcRepository;
}


동일 타입의 빈이 여러 개일 경우 다음과 같은 방법으로 빈을 구분한다.

  1. 필드명 매칭
  2. @Qualifier
  3. @Primary

 

1. 필드명 매칭

스프링은 타입으로 빈을 조회하고, 동일 타입 빈이 여러 개일 경우 이름으로 한번 더 빈을 조회한다.
따라서 구체 클래스(OracleRepository) 빈을 주입시키고 싶다면 아래와 같이 필드 명(혹은 파라미터 명)을 빈 이름으로 변경함으로써 해결할 수 있다.

// 필드 주입 예시
@Service
public class JdbcService {
    @Autowired
    private JdbcRepository oracleRepository;
}

//생성자 주입 예시
@Service
public class JdbcService {

    private final JdbcRepository jdbcRepository;
    
    public JdbcService(JdbcRepository oracleRepository) {
        this.jdbcRepository = oracleRepository;
    }
}

그러나 이 방법은 DIP를 위반하는 방법이므로 사용을 지양하고,
다음에 설명할 @Qualifier와 @Primary 어노테이션을 사용하는 방법으로 해결하자.

2. @Qualifier

@Qualifier는 어떤 빈을 사용할 것인지를 구분할 수 있는 구분자를 붙여주는 방식(빈 이름을 변경하는 것은 아님)이며 다음과 같이 사용한다.

// 필드 주입 예시
@Service
public class JdbcService {
    @Qualifier("oracleRepository") // 빈 이름에 맞는 클래스를 찾는다.
    @Autowired
    private JdbcRepository jdbcRepository;
}

// 생성자 주입 예시
@Service
public class JdbcService {
    private final JdbcRepository jdbcRepository;
    
    public JdbcService(@Qualifier("oracleRepository") JdbcRepository jdbcRepository) {
        this.jdbcRepository = jdbcRepository;
    }
}

 

3. @Primary

@Primary는 단어의 의미 그대로 우선순위를 정하는 방법이다.
여러 개의 등록된 빈 중 가장 높은 우선순위를 갖는다.

@Primary
@Repository
public class OracleRepository implements JdbcRepository {}

@Service
public class JdbcService {
    @Autowired
    private JdbcRepository jdbcRepository; // oracleRepository
}

만약 @Primary와 @Qualifier가 동시에 존재한다면 우선순위는 @Qualifier가 가진다.

반응형

블로그의 정보

슬기로운 개발생활

coco3o

활동하기