Develop/Spring (실습)

[Spring] @Primary 어노테이션

보보트레인 2024. 1. 10. 11:23

전제조건

1. Controller/ Service/ Repository로 구성되는 계층형 구조를 사용한다고 가정한다.

 

각 파일의 역할은 다음과 같다.

controller → api 진입시점

service → 예외처리 담당

Repository → SQL(DB통신) 담당

 

2. 각 레포지토리에는 통일된 인터페이스가 주입된다. (implements)


탄생배경

 

스프링의   IoC(Inversion of Control) 제어의 역전 속성을 이해해야 한다.

제어의 역전이란, 직접 특정인스턴스를 주입하지 않아도 스프링 컨테이너가 대신 생성자를 통해 적절한 레포지토리를 탐색하여 주입해준다는 것을 의미한다.


그렇다면?

만약 2가지 이상의 레포지토리가 같은 인터페이스를 상속받은 상태에서,

Service 클래스가 해당 인터페이스를 주입하려는 경우가 존재한다면 오류가 날 것이다.


왜?

어떤 레포지토리를 통해 주입하려는 인터페이스에 접근할지 ambiguous(모호한) 상태가 되기 때문.

(스프링 컨테이너가 어떤 레포지토리속 interface를 주입받을지 탐색할때, 같은것이 2개가 있으니 오류가 발생한다)


해결방법

이럴 경우 우리는 @Primary 어노테이션을 써서 레포지토리 접근 우선순위를 반드시 설정해주어야 한다..


실습

BookMysqlRepository와 BookMemoryRepository 2개의 레포지토리가 존재한다고 가정한다.

각각의 레포지토리는 BookRepository라는 Interface를 상속받는다.

@Repository
public class BookMySqlRepository implements BookRepository {
    @Override
    public void saveBook() {

    }
}
@Repository
public class BookMemoryRepository implements BookRepository {

    //private final List<Book> books = new ArrayList<Book>();
    @Override
    public void saveBook() {
        //books.add(new Book());
    }
}

 

만약 이런 상황에서 @Primary 어노테이션으로 우선순위를 설정해 주지 않는다면 서비스 코드에서 오류가 난다.

어떤 Repository의 bookRepository를 상속받을지 몰라서 스프링컨테이너상의 오류가 발생하는 중이다.


해결

//같은 이름의 레포지토리가 존재할 때, 이 스프링 빈이 우선권이 있어! 의미함.
@Primary
@Repository
public class BookMySqlRepository implements BookRepository {
    @Override
    public void saveBook() {

    }
}

만약 bookMySqlRepository를 우선시 하고 싶다고 가정할때,

@Primary 어노테이션을 해당 레포지토리에 위와 같이 사용한다면,

스프링 컨테이너는 bookMySqlRepository 가 implements받은 BookRepository를 자동으로 탐색하여 BookService에 주입할 것이다. - 오류 사라짐!

반응형