[SEB BE]Section 2. 다양한 DI(의존관계 주입)방법 4가지

박두팔이·2023년 2월 7일
0

스프링프레임워크

목록 보기
6/18

  • 스프링은 @Autowired 어노테이션을 이용한 다양한 의존성 주입(DI; Dependency Injection) 방법을 제공한다. 다시말하면 @Autowired는 Spring에게 의존성을 주입하는 지시자 역할로 쓰인다.

  • 의존성 주입은 필요한 객체를 직접 생성하지 않고 외부에서 객체를 받아 사용하는 것이다. -> 코드의 재활용 ⬆️


의존관계 주입 방법

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

1. 생성자 주입

생성자에 @Autowired 애너테이션을 붙여주면 스프링컨테이너에 등록된 Bean이 생성자에 필요한 빈(객체)들을 주입해준다.

  • 생성자 주입은 생성자 호출 시점에 딱 1번만 호출된다는 것을 보장해준다.
  • 생성자가 1개만 존재하는 경우는 @Autowired를 생략해도 자동 주입된다.
  • 생성자 주입을 사용하게 되면 NullPointerException을 방지할 수 있다.
  • 변하지 않는 필수 의존관계에서 생성자 주입방법을 DI방식으로 사용한다.
  • 따라서 주입받을 필드는 final로 선언이 가능하다.
@Component
public class CoffeeService {
  private final MemberRepository memberRepository;
  private final CoffeeRepository coffeeRepository;

  @Autowired
  public CoffeeService(MemberRepository memberRepository, CoffeeRepository coffeeRepository) {
    this.memberRepository = memberRepository;
    this.coffeeRepository = coffeeRepository;
  }
}

👩🏻‍🏫 생성자 주입 방식의 장점!!

1. 불변

  • 의존관계 설정이 되지 않으면 객체생성이 불가능하다. 따라서,
    👉🏻 컴파일 타임에 인지가 가능하다.
    👉🏻 NPE(Null Point Exception)에러 방지가 가능하다.

의존관계 주입은 애플리케이션이 실행~종료 전까지 변경되어져선 안된다. 수정자 주입 같은 경우 메서드를 public으로 열어두었기 때문에 변경이 가능하여 적합하지 않다.

왜냐하면 누군가 실수로 변경할 수 있는 가능성도 있고 애초에 변경되면 안되는 메서드가 변경되는 것은 좋은 설계방법이 아니다.

2. final 키워드 사용 가능

  • 의존성 주입이 필요한 필드를 final로 선언이 가능하다.

생성자 주입을 사용하면 필드에 final 키워드를 사용 할 수 있다. 생성자 주입을 제외한 나머지 주입방식은 생성자 이후 호출되는 형태이기 때문에 final키워드를 사용할 수 없다. 또한 생성자에서 값이 설정되지 않으면 컴파일 시점에서 오류를 확인할 수 있다.

// 오류
java: variable (데이터 이름) might not have been initialized

3. 누락

  • 호출했을 때는 NPE(Null Point Exception)이 발생하는데 의존관계 주입이 누락되었기 때문에 발생한다.

  • 생성자 주입을 사용하면 주입 데이터 누락 시 컴파일 오류가 발생한다.

    • 스프링에서 순환참조감지가 가능하다.
      👉🏻 순환 참조 시 앱구동이 실패하게 된다.
  • 테스트 코드 작성이 용이하다.
  • 수정자 주입이 필요한 경우가 있을 수 있지만 옵션이 필요할 때만 선택하면 된다.

2. 수정자 주입(Setter주입)

setter라 불리는 필드 값을 변경하는 setter()메서드를 통해 의존관계를 주입하는 방법이다.

  • 앞서 불변과 필수의존관계에서 생성자 주입을 사용했다면 수정자 주입은 선택과 변경의 가능성이 있는 의존관계에서 사용된다.
  • setter()메서드를 사용한다.
@Component
public class CoffeeService {
  private MemberRepository memberRepository;
  private CoffeeRepository coffeeRepository;

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

  @Autowired
  public void setCoffeeRepository(CoffeeRepository coffeeRepository) {
    this.coffeeRepository = coffeeRepository;
  }
}
  • set+필드이름의 메서드를 생성하여 의존관계를 주입하는 것이 생성자 주입과의 차이점이다.

  • 수정자메서드에는 @Autowired를 입력해야만 실행된다.

  • 생성자가 1개일 때 @Autowired를 입력하지 않아도 작동이 되는 이유는,

  • 스프링이 클래스(객체)를 빈에 등록할 때 생성자를 부를 수 밖에 없는데 그 때 의존관계주입도 같이 발생하게 되기 때문이다.


필드주입

필드에 @Autowired 붙여서 바로 주입하는 방법이다.

  • 코드가 간결해서 예전에 많이 사용되던 방식이다. 그러나 외부에서 변경이 불가능하기 때문에 테스트하기 힘든 단점이 있다.
  • DI 프레임워크가 없으면 아무것도 할 수없다.
  • 실제 코드와 상관없는 특정 테스트를 하고싶을 때 사용할 수 있다.
  • 하지만 정상적인 작동을 위해선 결국 setter가 필요하기 때문에 수정자 주입을 사용하는 것이 더 편리해진다.
@Component
public class CoffeeService {
  @Autowired
  private MemberRepository memberRepository;
  @Autowired
  private CoffeeRepository coffeeRepository;
}

일반 메서드 주입

일반 메서드를 사용해 주입하는 방법이다.

  • 한번에 여러 필드를 주입받을 수 있다.
  • 일반적으로 사용되지 않는다.

profile
기억을 위한 기록 :>

0개의 댓글