# 생성자 주입을 선택해라!

과거에는 수정자 주입과 필드 주입을 많이 사용했지만, 최근에는 스프링을 포함한 DI 프레임워크 대부분이 생성자 주입을 권장한다.&#x20;

<생성자 주입의 장점>

1. 불변

* 대부분의 의존관계 주입은 한번 일어나면 애플리케이션 종료시점까지 의존관계를 변경할 일이 없다. 오히려 대부분의 의존관계는 애플리케이션 종료 전까지 변하면 안된다.(불변해야 한다.)
* 생성자 주입은 객체를 생성할 때 딱 1번만 호출되므로 이후에 호출되는 일이 없다. 따라서 불변하게 설계할 수 있다.
* **생성자 주입**을 사용하면 **필드에 final 키워드를 사용**할 수 있다. 그래서 생성자에서 혹시라도 값이 설정되 지 않는 오류를 컴파일 시점에 막아준다. 다음 코드를 보자.\
  잘 보면 필수 필드인 discountPolicy 에 값을 설정해야 하는데, 이 부분이 누락되었다!!! 자바는 컴파일 시 점에 다음 오류를 발생시킨다.

```java
@Component
    public class OrderServiceImpl implements OrderService {
        private final MemberRepository memberRepository;
        private final DiscountPolicy discountPolicy;
@Autowired
        public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy
    discountPolicy) {
            this.memberRepository = memberRepository;
            //여기에 discountPolicy 값 설정 누락!!
        }
//...
}
```



❌사용하면 안 되는 이유❌

수정자 주입을 포함한 나머지 주입 방식은 모두 생성자 이후에 호출된다. final 키워드는 무조건 값을 넣어줘야하는데 수정자 주입이나 다른 주입 방식은 모두 생성자 이후에 호출되므로 final 키워드를 사용할 수 없다! (오직 생성자 주입 방식만 final 키워드를 사용할 수 있다. 객체를 생성하면서 바로 DI를 해준다💚)

필드 주입 : 필드에서 이미 다 정해지기 때문에 DI 프레임워크가 없으면 테스트조차하기 힘들다는 치명적인 단점이 있다.\
다음과 같은 경우는 필드 주입을 사용할 수도 있다!\
\=>애플리케이션의 실제 코드와 관계 없는 테스트코드\
\=>스프링 설정을 목적으로 하는 @Configuration 같은 곳에서만 특별한 용도로 사용

수정자 주입 : setXxx 메서드를 public으로 열어두어야 한다. 누군가 실수로 변경할 수 도 있고, 변경하면 안되는 메서드를 열어두는 것은 좋은 설계 방법이 아니다!\
(가끔 옵션이 필요하면 수정자 주입을 선택할 수도 있다.)
