스프링의 다양한 의존관계 주입 방법

gwjeon·2021년 9월 30일
1
post-custom-banner


학습참조
인프런-스프링 핵심 원리 기본편(김영한님)


의존관계 주입은 크게 4가지 방법이 있다.

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

✅ 생성자 주입

@Component
public class MemberServiceImpl implements MemberService {

    private final MemberRepository memberRepository;

    @Autowired // 생성자 의존관계 주입
    public MemberServiceImpl(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }
}
  • 이름 그대로 생성자를 통해 의존 관계를 주입 받는 방식이다.
  • 스프링이 MemberServiceImpl를 스프링 컨테이너에 등록하는 과정에서 생성자를 호출할 때 생성자에 @Autowired Annotation이 있다면 매개변수에 해당하는 타입의 빈을 스프링 컨테이너에서 꺼내와 자동으로 주입한다.
  • 생성자를 호출하는 시점에 딱 1번만 호출되는 것이 보장된다.
  • 불변, 필수적인 의존관계에 사용한다.
  • ※ 생성자가 딱 1개만 있으면 @Autowired를 생략해도 자동 주입된다. *물론 스프링 빈에만 해당함.

✔ 생성자 주입의 비밀(?)

사실 생성자 주입과 다른 방식의 의존관계 주입과는 다른점이 있다. 생성자 주입은 컨테이너에 등록하는 과정과 의존관계 주입이 동시에 일어나지만 다른 방식의 의존관계 주입은 컨테이너에 등록하는 행위와 의존관계를 주입하는 행위가 나누어져 있다.

생성자 주입은 스프링이 Class를 스프링 컨테이너에 등록하면서 스프링이 아무리 마술사처럼 멋진 기능을 수행한다 하여도 어쨌든간에 스프링도 자바를 기반으로 하기에 자바 문법상 자동으로 생성자를 호출해야 함으로 이때 @Autowired Annotation이 있으면 Parameter에 해당하는 데이터 타입의 빈이 존재한다면 꺼내서 주입시키고 존재하지 않는다면 해당 데이터 타입의 Class를 찾아서 컨테이너에 등록후 의존관계를 주입한다.


✅ 수정자 주입(setter 주입)

@Component
public class MemberServiceImpl implements MemberService {

    private MemberRepository memberRepository;

    @Autowired
    public void setMemberRepository(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }
}
  • setter를 이용한 의존관계를 주입하는 방식이다.
  • 수정자 주입은 스프링이 MemberServiceImpl를 스프링 컨테이너에 등록한 후 @Autowired Annotation이 있다면 의존관계 주입을 수행한다.
  • 선택, 변경 가능성이 있는 의존관계에 사용한다.
  • ※ 선택적으로 의존관계를 주입하고 싶다면(회원 등급에 따른 정책 변경 이라던지...), 만약 MemberRepository가 스프링 컨테이너에 등록이 안되어 있다면? @Autowired(required = false) 옵션을 이용하자. 그렇지 않다면 에러가 발생.

✅ 필드 주입

public class MemberServiceImpl implements MemberService {

    @Autowired private final MemberRepository memberRepository;
}
  • 필드 선언 앞에 @Auotowired Annotation을 넣음으로써 필드에 바로 주입하는 방식이다.
  • 코드가 간결해서 많은 개발자들을 유혹하지만, 외부에서 변경이 불가능 하기에 테스트가 어려운 치명적인 단점이 있음.
  • 외부에서 의존관계를 주입해주는 DI 프레임워크가 없기 때문에 아무것도 할 수 없음.
  • 가능하면 사용을 자제하되 다음과 같은 경우에는 사용해도 무방함.
    • 애플리케이션의 실제 코드와 관계 없는 테스트 코드
    • 스프링 설정을 목적으로 하는 @Configuration Annotation 같은 경우에만 특별한 용도로 사용

✅ 일반 메서드 주입

@Component
public class MemberServiceImpl implements MemberService {

    private MemberRepository memberRepository;

    @Autowired
    public void injectionInit(MemberRepository memberRepository) {
            this.memberRepository = memberRepository;
    }
}
  • 일반 메서드를 통해 주입하는 방식이다.
  • 한번에 여러 필드를 주입 할 수 있다.
  • 사실 수정자 주입(setter 주입)과 별 다를바 없이 동일하다고 봐도 무방하다.
  • 생성자 주입과 수정자 주입으로도 충분함으로 사용하지 않는다.
profile
ansuzh
post-custom-banner

0개의 댓글