Spring 핵심 원리 TIL - DI 방법 정리

YulHee Kim·2021년 8월 23일
0

Spring 핵심 원리

목록 보기
5/13
post-thumbnail

Spring 핵심원리 TIL 😎
[참고 강의] 김영한님의 스프링 핵심 원리 - 기본편

오늘은 각 의존성 주입의 장단점을 비교해보겠습니다.
이를 통해 왜 강사님께서 생성자 주입을 권장하셨는지 알아보겠습니다 !

💡 3가지의 DI 방법

의존성 주입은 크게 3가지로 나눠집니다.

1. 생성자 주입
2. 필드 주입
3. Setter 주입

단순히 생성자 주입이 더 좋다고만 알고있었지 구체적으로 왜 좋은진 몰랐습니다..
지금부터 차근차근 알아가보겠습니다

✏️ 필드 주입

변수 선언부에 @Autowired Annotation을 붙이면 자동으로 의존성이 주입됩니다.

@Component
public class MadExample {

    @Autowired
    private HelloService helloService;
}

선언 자체는 매우 편리하지만 단점이 있습니다. 😱

  • 외부에서 변경이 불가능해서 테스트하기 힘들다는 것이 단점입니다.
  • DI 프레임워크가 존재해야합니다.
    순수한 자바코드에선 @Autowired는 동작하지 않습니다.. ㅠㅠ

✏️ Setter 주입

Setter injection은 상황에 따라 의존성 주입이 가능합니다.
set Method를 정의해서 사용합니다.

@Component
public class SampleController {
    private SampleService sampleService;
 
    @Autowired
    public void setSampleService(SampleService sampleService) {
        this.sampleService = sampleService;
    }
}

Setter Injection을 통해서 Service의 구현체를 주입해주지 않아도 Controller 객체는 생성이 가능합니다.

주입이 필요한 객체가 주입이 되지 않아도 얼마든지 객체를 생성할 수 있다는 것이 문제입니다.
@Autowired로 주입할 대상이 없는 경우에는 오류가 발생합니다.
그리고 Public이라 나중에 잘못 변경되면 문제가 발생합니다.

위 필드 주입, 세터 주입 문제를 해결 할 수 있는 방법이 Constructor Injection입니다.

✏️ 생성자 주입

public class OrderServiceImpl implements OrderService {

    private final MemberRepository memberRepository;
    private final DiscountPolicy discountPolicy;

    public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
        this.memberRepository = memberRepository;
        this.discountPolicy = discountPolicy;
    }
  • 생성자 호출시점에 딱 1번만 호출되는 것이 보장됩니다.
  • final을 선언할 수 있으므로 객체가 불변하도록 설계할 수 있습니다.
  • 단일 생성자라면 @Autowired를 붙이지 않아도 됩니다.
  • 생성자 주입을 사용하면 의존성 주입을 누락하는 것을 방지할 수 있다고 합니다. IDE에서 컴파일 오류로 알려줍니다.
  • 순환 의존성 여부도 파악할 수 있습니다. BeanCurrentlyCreationExeption을 발생시킴으로써 순환 의존성을 알 수 있습니다.

순환 의존성?

A Class가 B Class를 참조하는데 B Class가 다시 A Class를 참조할 경우,
A Class가 B Class를 참조하고, B Class가 C Class를 참조하고 C Class가 A Class를 참조하는 경우 이를 순환 의존성(Circular Dependency)이라고 부른다.

final 키워드

변수에 final을 붙이면 이 변수는 수정할 수 없다는 의미를 가집니다.
수정될 수 없기 때문에 초기화 값은 필수적입니다.
만약에 객체안의 변수라면 생성자, static 블럭을 통한 초기화까지는 허용합니다.

생성자 주입을 활용할 경우 final을 통해 값의 불변을 보장할 수 있습니다.
생성자를 통해 딱 한번 의존성을 설정하고 변경할 일이 없으므로 안전하게 값의 불변을 보장합니다.

이러한 장점 때문에 스프링은 생성자 주입 방식을 권장합니다 😃

즉, 생성자 주입을 이용하면 원하는 구현체를 주입할 수 있고,
프레임워크의 도움 없이 순수 자바 코드로 테스트를 실행할 수 있습니다 !

참고
링크1
링크2
링크3

profile
백엔드 개발자

0개의 댓글