스파이더 웹 개발

의존관계 자동 주입 본문

Spring

의존관계 자동 주입

스파이더웹 2022. 7. 31. 16:48
728x90
반응형

의존관계의 주입 방법 종류

  1. 생성자 주입
  2. 수정자 주입(setter 주입)
  3. 필드 주입

생성자 주입

- 생성자를 통해 의존관계를 주입받는 방법

- 특징

  • 생성자 호출시점에 1번만 호출되는 것이 보장
  • 불변성을 가진다

생성자 주입

@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;
    }

 

 

수정자 주입

선택, 변경 가능성이 있는 의존관계에 사용

수정자 주입

@Component
public class OrderServiceImpl implements  OrderService{

    private  MemberRepository memberRepository;
    private  DiscountPolicy discountPolicy;

    @Autowired
    public void setMemberRepository(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }

    @Autowired
    public void setDiscountPolicy(DiscountPolicy discountPolicy) {
        this.discountPolicy = discountPolicy;
    }

 

필드 주입

쓰지말자!

- 스프링 설정 목적으로 하는 @Configuration 같은 곳에서만 사용하자

 - 테스트 코드 정도에서 사용하자

 

필드 주입

@Component
public class OrderServiceImpl implements  OrderService{


    @Autowired
    private final MemberRepository memberRepository;
    @Autowired
    private final DiscountPolicy discountPolicy;

 

의존성 주입 중 생성자 주입을 선택해서 사용하도록하자

why?

1. 불변성을 가짐

2. 테스트의 용이하다

3. 순환참조 방지

 

대부분의 경우 생성자 주입을 채택하는데 롬복을 설치하여 @RequiredArgsConstructor(final이 붙은 필드를 모아서 생성자를 자동으로 만들어 준다) 어노테이션을 사용하여

생성자의 생성을 생략할 수 있다.(@Autowired도 생성자가 1개일때는 생략가능하므로 해당 어노테이션또한 생략이 가능하다)

@RequiredArgsConstructor
@Component
public class OrderServiceImpl implements  OrderService{

    private final MemberRepository memberRepository;
    private final DiscountPolicy discountPolicy;

 

조회 빈이 2개이상시 발생하는 문제

@Autowired는 타입으로 조회한다(이름으로 조회하지 않음) 그러므로 선택된 빈이 2개이상인 경우 문제가 발생하는데

예를 들어 아래의 경우

@Component
public class RateDiscountPolicy implements DiscountPolicy

@Component
public class FixDiscountPolicy implements DiscountPolicy

@Autowired
private DiscountPolicy discountPolicy

NoUniqueBeanDefinitionException 오류가 발생한다

그 이유는 빈이 2개가 발견되었다는 내용이다

 

이를 해결하기위해서는 다양한 방법이있는데

1. @Autowired는 타입을 조회하고  여러 빈이 있으면 필드 이름, 파라미터 이름으로 빈이름 추가 매칭한다

   //생성자 주입
   @Autowired
    public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
        this.memberRepository = memberRepository;
        this.discountPolicy = discountPolicy;
    }
    
//이전 코드에서는 FixDiscountPolicy, RateDisCountPolicy의 2개의 빈을 설정하였을 경우 예외가 발생하였다
//파라미터의 이름을 특정 빈의 이름으로 변경하게 되면 예외가 발생하지 않고 해당빈의 이름으로 매칭이 된다

    @Autowired
    public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy rateDiscountPolicy) {
        this.memberRepository = memberRepository;
        this.discountPolicy = rateDiscountPolicy;
    }

 

2. @Quilifier 사용(추가적인 구분역할을 해주는 어노테이션)

@Component
@Qualifier("별칭")
public class RateDiscountPolicy implements DiscountPolicy

@Component
public class FixDiscountPolicy implements DiscountPolicy

@Autowired
    public OrderServiceImpl(MemberRepository memberRepository, @Qualifier("설정한 별칭") DiscountPolicy discountPolicy) {
        this.memberRepository = memberRepository;
        this.discountPolicy = discountPolicy;
    }

해당 어노테이션을 사용하면 별칭이 붙은 빈을 찾는다

 

3. @Primary 사용 (우선 순위 지정)

@Component
@Primary
public class RateDiscountPolicy implements DiscountPolicy

@Component
public class FixDiscountPolicy implements DiscountPolicy

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

해당 어노테이션이 붙은 빈이 우선권을 가진다

 

@Primary 와 @Qualifier 충돌시 @Qualifier이 우선권을 가진다

 

 

참조 

스프링 핵심원리 - 김영한님

728x90
반응형

'Spring' 카테고리의 다른 글

빈 스코프  (0) 2022.08.07
빈 생명주기 콜백  (0) 2022.08.03
컴포넌트 스캔  (0) 2022.07.30
싱글톤 컨테이너  (0) 2022.07.29
스프링 컨테이너와 스프링 빈  (0) 2022.07.25
Comments