오봉이와 함께하는 개발 블로그

Spring - 의존관계 자동 주입(다양한 의존관계 주입 방법) 본문

BE/Spring

Spring - 의존관계 자동 주입(다양한 의존관계 주입 방법)

오봉봉이 2022. 6. 9. 19:11
728x90

다양한 의존관계 주입 방법

  • 의존관계 주입은 크게 4가지 방법이 있다.
    • 생성자 주입
    • 수정자 주입(setter 주입)
    • 필드 주입
    • 일반 메소드 주입

생성자 주입

  • 생성자를 통해 의존관계를 주입 받는 방법
  • 지금까지 진행했던 방법이 생성자 주입이다.
  • 구현체를 스프링 빈에 등록할 때 같이 이뤄진다.
  • 컴포넌트 스캔을 하며 @Autowired가 있는 생성자를 찾고 스프링 빈에서 필요한 객체들을 찾아 주입한다.
    • 생성자가 딱 1개만 있으면 @Autowired를 생략해도 자동 주입 된다.
  • 특징
    • 생성자 호출시점에 딱 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;
      }
      // @Autowired 생략
      /*
      public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
          this.memberRepository = memberRepository;
          this.discountPolicy = discountPolicy;
      }
      */
}

수정자 주입(setter 주입)

  • setter라 불리는 필드의 값을 변경하는 수정자 메소드를 통해 의존관계를 주입
  • @Autowired가 없으면 안 된다.
  • 스프링 빈 라이프사이클에 의해 컨테이너를 생성하고 빈을 등록한 다음 주입이 된다.
  • 특징
    • 선택, 변경 가능성이 있는 의존관계에 사용함.
      • 객체가 스프링 빈에 등록되지 않았을 때도 사용 가능하기 때문에 선택적으로 주입을 한다.
      • @Autowired(required = false)가 필요함
      • 변경이 필요하면 외부에서 강제로 호출하여 사용할 수 있다.
@Component
public class OrderServiceImpl implements OrderService{

    private MemberRepository memberRepository;
    private DiscountPolicy discountPolicy;

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

필드 주입

  • 필드에 바로 주입하는 방법
  • 특징
    • 코드가 간결하지만 외부에서 변경이 불가능해서 테스트 하기 힘든 치명적인 단점이 있다.
    • DI 프레임워크가 없으면 아무것도 할 수 없다.
      • 스프링에 의존하기 때문에 순수한 자바코드로 테스트를 할 수 없다.
    • 사용하지 않는 것을 추천한다
      • 앱의 실제 코드와 관계 없는 테스트 코드에서 사용
      • 스프링 설정 목적으로 하는 @Configuration 같은 곳에서만 특별한 용도로 사용
@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;
        }
}

외전

DI는 스프링 컨테이너가 관리하는 스프링 빈이어야 동작을 한다(@Component) 스프링 빈이 아닌 일반 자바 클래스에서 @Autowired를 적용해도 아무 기능 없다

출처 : 인프런 김영한 지식공유자님의 스프링 완전 정복 로드맵 강의
728x90
Comments