본문 바로가기
Learning-log/Spring & JPA

(스프링 핵심 원리 - 기본편) 7-(4) 롬복과 최신 트랜드, (5)조회 빈이 2개 이상 - 문제, (6)@Autowired필드 명, @Qualifier, @Primary

by why제곱 2023. 4. 8.

- 롬복과 최신 트랜드

  • 개발의 대부분은 다 불변, 그래서 생성자에 final을 사용하게 됨
  • 그런데 생성자도 만들어야하고 주입 받은 값을 대입하는 코드도 만들어야 하는데 필드 주입처럼 편하게 사용하는 방법은? 
  • 기존의 OrderServiceImpl코드를 최적화해보자.
  • 최적화 전
@Component
public class OrderServiceImpl implements  OrderService{

    private final MemberRepository memberRepository;
    private final DiscountPolicy discountPolicy;
    
    @Autowired
    public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
        this.memberRepository = memberRepository;
        this.discountPolicy = discountPolicy;
    }
    
    ...
    }
  • 설정
    1. 생성자 하나이므로 @Autowired생략 가능
    2. Build.gradle파일에 lombok 설정 추가
    3.  File- Settings에 들어가서 Plugins에서 'Lombok' 검색 후 설치하기
    4. File - Settings - Build, Execution, Deployment 의 Annotation Process에서 아래 사진과 같이 설정 변경
    5.  

2. Build.gradle에서 lombok 설정
2. Build.gradle에서 lombok 설정

 

3. File -Settings - Plugin에서 Lombok 설치
3. File - Settings - Build, Execution, Deployment 의 Annotation Process에서 Enable annotation processing check하기

 

  • '@Getter', '@Setter' ,  '@ToString' 등 :  Getter, Setter, 생성자, toString 을  코드로 짜지 않아도 생성해줌 ! 
  • 최적화 후 코드
@Component
@RequiredArgsConstructor
public class OrderServiceImpl implements OrderService {
 private final MemberRepository memberRepository;
 private final DiscountPolicy discountPolicy;
}
  • 새로운 의존관계가 생겼을 때, 'private final ~ ' 만 추가해주면 돼서 편함
  • 최근에는 생성자 1개만 두고 @Autowired 생략하는 방법 주로 사용. 여기에 Lombok 라이브러리의 @RequiredArgsProcessor을 함께 사용하면 원하는 기능을 다 사용하면서 코드 깔끔하게 정리 가

 

- 조회 빈이 2개 이상 - 문제 

 

  • @Autowired는 기본적으로 타입으로 조회
  • 타입으로 조회하면 해당 타입의 빈이 두 개 이상일 때 문제 발생
  • 하위타입을 지정할 수 있지만 이러면 DIP를 위배하고 유연성이 떨어짐. 이름만 다르고 완전히 똑같은 타입의 스프링빈이 2개 있을 때 해결이 안 됨.

 

- @Autowired필드 명, @Qualifier, @Primary

  • 위 문제의 해결 방법
    • @Autowired의 필드명 매칭
      • 타입 매칭을 시도하고 여러개의 빈이 있으면 필드 이름, 파라미터 이름으로 빈 이름을 추가 매칭함
    • @Qualifier -> @Qualifier 끼리 매칭 => 빈 이름 매칭
      • 추가 구분자를 붙여주는 방법. 주입 시 추가적인 방법을 제공할 뿐 빈 이름 변경은 아님
      • 빈 등록 시 @Qualifier 붙여주기
      • 이 때 저 Qualifier로 매칭된 빈을 못 찾으면 어떻게 될까?
        • 그 다음에 못 찾으면 mainDiscountPolicy라는 이름의 스프링 빈을 추가로 찾음
      • Bean직접 등록 시에도 사용 가능

  • @Primary
    • 자주 사용, 편하긴 하지만 한계점 존재
    • 우선 순위를 정하는 방법
    • @Primary가 지정되어 있으면 우선 선택 됨
    • 예를 들어 메인 데이터베이스가 95% 보조 데이터베이스가 5%일 때 매번 qualifier지정이 번거로우므로 이 때 primary를 사용
  • Primary와 Quailifier 중 뭘 사용할까? 
    • 코드에서 자주 사용하는 메인데이터베이스, 가끔 사용하는 서브 데이터베이스의 커넥션을 획득하는 스프링 빈이 있다고 하자. 메인은 @Primary 적용하고 서브를 커넥션 할 때는 @Qualifier를 적용해서 명시적으로 획득하는 방법을 사용하면 코드 깔끔하게 유지 가능
    • 우선순위는 @Primary는 기본값처럼 동작하고 @Qualifier는 세부적으로 동작하는 것이므로 둘 다 동시 실행될 땐 Qualifier가 우선 실행됨.