스프링 핵심원리 기본편2

진연석

Updated:

Intro

김영한님의 Spring 핵심원리 기본편을 듣고 정리한 내용을 공유합니다.

조회 대상 빈이 2개 이상일 때 해결 방법

1. @Autowired 필드 명 매칭

  • DiscountPolicy의 구현체는 fixDiscountPolicy, rateDiscountPolicy가 있다고 가정
    // 기존코드
    @Autowired
    private DiscountPolicy discountPolicy
    
    // 수정코드
    @Autowired
    private DiscountPolicy rateDiscountPolicy
    

    @Autowired는 타입 매칭을 시도하고, 이때 여러 빈이 있으면 필드 이름, 파라미터 이름으로 빈 이름을 추가 매칭한다. 필드명이 rateDiscountPolicy이므로 정상적으로 주입된다.

    2. @Qualifier는 @Qualifier끼리 매칭

    1. @Qualifier는 추가 구분자를 붙여주는 방법
    2. 주입 시 추가적인 방법을 제공하는 것이지 빈 이름을 변경하는 것은 아니다.
// RateDiscountPolicy.class
@Component
@Qualifier("mainDiscountPolicy")
public class RateDiscountPolicy implements DiscountPolicy{

    private int discountPercent = 10;


    @Override
    public int discount(Member member, int price) {
        if(member.getGrade() == Grade.VIP) {
            return price * discountPercent / 100;
        } else {
            return 0;
        }
    }
}
// FixDiscountPolicy.class
@Component
@Qualifier("fixDiscountPolicy")
public class FixDiscountPolicy implements DiscountPolicy {

    private int discountFixAmount = 1000; // 1000원 할인

    @Override
    public int discount(Member member, int price) {
        if(member.getGrade() == Grade.VIP) {
            return discountFixAmount;
        } else {
            return 0;
        }
    }
}

이제 위에 코드처럼 설정해두고 사용 할 때는 다음과 같이 설정 할 수 있다.

public class OrderServiceImpl implements OrderService {

    private final MemberRepository memberRepository;
    private final DiscountPolicy discountPolicy;

    public OrderServiceImpl(MemberRepository memberRepository, @Qualifier("mainDiscountPolicy") DiscountPolicy discountPolicy) {
        this.memberRepository = memberRepository;
        this.discountPolicy = discountPolicy;
    }
}

3. @Primary 사용

@Primary는 우선순위를 정하는 방법이며, @Autowired시에 여러 빈이 매칭되면 @Primary가 우선권을 가진다.

@Component
public class FixDiscountPolicy implements DiscountPolicy {

    private int discountFixAmount = 1000; // 1000원 할인

    @Override
    public int discount(Member member, int price) {
        if(member.getGrade() == Grade.VIP) {
            return discountFixAmount;
        } else {
            return 0;
        }
    }
}
@Component
@Primary
public class RateDiscountPolicy implements DiscountPolicy{

    private int discountPercent = 10;

    @Override
    public int discount(Member member, int price) {
        if(member.getGrade() == Grade.VIP) {
            return price * discountPercent / 100;
        } else {
            return 0;
        }
    }
}

이렇게 primary가 있으면 여러 빈이 선택되어도 다른것을 다 무시하고 RateDiscountPolicy를 우선순위를 최상으로 하여 의존관계 주입한다.

4. @Primary, @Qualifier 활용

코드에서 자주 사용하는 메인 데이터베이스의 커넥션을 획득하는 스프링 빈이 있고, 코드에서 특별한 기능으로 가끔 사용하는 서브 데이터베이스의 커넥션을 획득하는 스프링 빈이 있다고 했을 경우

  1. 메인 데이터베이스의 커넥션 획득
    • @Primary를 적용하여 조회하는 곳에서 @Qualifier 지정 없이 편리하게 조회
  2. 서브 데이터베이스 커넥션 획득
    • @Qualifier를 지정하여 명시적으로 획득하는 방식
  3. @Primary와 @Qualifier의 우선순위
    • @Primary(넓은 범위)는 기본 값처럼 동작하고, @Qualifier(좁은 범위)는 상세하게 동작하기에 좁은 범위의 선택권을 가진 @Qualifier의 우선 순위가 높다.

5. 빈 생성주기 콜백

  1. 스프링 빈의 이벤트 라이프사이클
    • 스프링 컨테이너 -> 생성 스프링 빈 생성 -> 의존관계 주입 -> 초기화 콜백 -> 사용-> 소멸전 콜백 -> 스프링 -> 종료
  2. 객체의 생성과 초기화를 분리
    • 생성자는 객체 생성에 책임을 가진다.
    • 초기화는 생성된 값들을 활용하여 커넥션 연결과 같은 무거운 동작을 수행한다.
  3. 스프링의 빈 생명주기 콜백 지원 방법
    • 인터페이스(initializingBean, DisposableBean) -> 거의 사용하지 않음
    • 설정 정보에 초기화 메서드나 종료 메서드 지정 -> @Bean(initMethod = “init”, destroyMethod = “close”)
    • @PostConstruct, @PreDestory 에너테이션 지원

Leave a comment