의존관계 자동 주입

yseo14·2023년 7월 3일

Spring

목록 보기
5/7

의존관계 주입에는 다양한 방법이 있다.

  • 생성자 주입
  • 수정자 주입 (setter)
  • 필드 주입
  • 일반 메서드 주입

생성자 주입

이름 그대로 생성자를 통해서 의존 관계를 주입 받는 방법.

특징

  • 생성자 호출 시점에 딱 한 번만 호출되는 것이 보장됨
  • "불변, 필수" 의존관계에 사용
@Component
public class OrderServiceImpl implements OrderService {

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

수정자 주입(setter 주입)

setter라 불리는 필드의 값을 변경하는 수정자 메서드를 통해서 의존관계를 주입하는 방법

특징

  • "선택, 변경" 가능성이 있는 의존관계에 사용
  • 자바빈 프로퍼티 규약과 수정자 메서드 방식을 사용하는 방법이다.
@Component
public class OrderServiceImpl implements OrderService {

    private MemberRepository memberRepository;
    private DiscountPolicy discountPolicy;


    @Autowired
    public void setMemberRepository(MemberRepository memberRepository) {
        System.out.println("memberRepository = " + memberRepository);
        this.memberRepository = memberRepository;
    }

    @Autowired
    public void setDiscountPolicy(DiscountPolicy discountPolicy) {
        System.out.println("discountPolicy = " + discountPolicy);
        this.discountPolicy = discountPolicy;
    }
}

필드 주입

이름 그대로 필드에 바로 주입하는 방법.

특징

  • 코드가 간결해서 많은 개발자들을 유혹하지만 외부에서 변경이 불가능해서 테스트하기 힘들다는 단점이 있음.ㅍ
  • DI 프레임워크가 없다면 아무것도 할 수 없음.
  • 그냥 사용하지 말 것.
@Component
    public class OrderServiceImpl implements OrderService {
    
        @Autowired
        private MemberRepository memberRepository;
        @Autowired
        private DiscountPolicy discountPolicy;
}

일반 메서드 주입

일반 메서드를 통해 주입 받을 수 있다.

특징

  • 한번에 여러 필드를 주입 받을 수 있다.
  • 일반적으로 잘 사용하지 않음.
@Component
    public class OrderServiceImpl implements OrderService {
        private MemberRepository memberRepository;
        private DiscountPolicy discountPolicy;
		
        @Autowired
        public void init(MemberRepository memberRepository, DiscountPolicy
    discountPolicy) {
            this.memberRepository = memberRepository;
            this.discountPolicy = discountPolicy;
        }
}

옵션 처리

주입할 스프링 빈이 없더라도 동작해야할 때가 있음.
하지만 @Autowired만 사용하면 'required' 옵션의 기본 값이 'ture'로 설정되어 있기 때문에 자동 주입 대상이 없으면 오류가 발생함.

자동 주입 대상을 옵션으로 처리하는 방법

  • @Autowired(required=false) : 자동 주입할 대상이 없으면 수정자 메서드 자체가 호출 안됨
  • org.springframework.lang.@Nullable : 자동 주입할 대상이 없으면 null이 입력됨
  • Optional<> : 자동 주입할 대상이 없으면 Optional.empty 가 입력됨

생성자 주입을 선택할 것..!

  • 생성자 주입을 선택하는 이유는 여러가지가 있지만, 프레임워크에 의존하지 않고, 순수한 자바 언어의 특징을 잘 살리는 방법임
  • 기본으로 생성자 주입을 사용하고, 필수 값이 아닌 경우에는 수정자 주입 방식을 옵션으로 부여.
  • 항상 생성자 주입을 선택하고 가끔 옵션이 필요하면 수정자 주입을 선택. 필드 주입은 사용하지 말 것.

조회 빈이 2개 이상일 때

@Autowired는 타입(Type)으로 조회한다.
DiscountPolicy 의 하위 타입인 RateDiscountPolicy와 FixDiscountPolicy가 둘다 스프링 빈으로 선언되어있다면?

-->NoUniqueBeanDefinitionException 오류 발생

해결 방법

  • @Autowired 필드 명 매칭
  • @Qualifier 사용

  • @Primary 사용

*Qualifier와 Primary의 우선 순위는 더 상세하게 동작하는 Qualifier임.

profile
like the water flowing

0개의 댓글