의존관계 주입은 크게 4가지 방법이 있다.
- 생성자 주입
- 수정자 주입 (setter 주입)
- 필드 주입
- 일반 메서드 주입
👉 과거에는 수정자 주입이나 필드 주입을 많이 사용했으나 최근에는 생성자 주입을 권장하고 있다.
그 이유는 크게 두 가지인데 불변 과 누락 이다.
대부분의 의존관계 주입은 한 번 일어나면 애플리케이션 종료 시점까지 변경할 일이 없고 변하면 안 된다. 그런데 수정자 주입을 사용하는 경우에는 set~ 메서드를 public으로 생성하기 때문에 누군가 실수로 변경할 수도 있다. (변하면 안되는 메서드를 public으로 열어두는 것은 좋지 않다.)
생성자 주입은 객체 생성시 딱 한 번만 호출되기 때문에 이후에 호출되는 일이 없어 불변하게 설계할 수 있다.
프레임워크 없이 순수 자바 코드를 단위테스트 하는 경우를 보자.
@Autowired가 프레임워크 안에서 동작하지 않기 때문에 의존관계가 없다고 오류가 발생하지 않는다. (프레임 워크 안에서는 오류가 발생함) public class OrderServiceImpl implements OrderService {
private MemberRepository memberRepository;
private DiscountPolicy discountPolicy;
@Autowired
public void setMemberRepository(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
@Autowired
public void setDiscountPolicy(DiscountPolicy discountPolicy) {
this.discountPolicy = discountPolicy;
}
...
}
테스트도 실행은 가능하나 의존관계 주입이 누락되었기 때문 NullPointException이 발생한다.

생성자 주입을 사용하면 final 키워드를 사용할 수 있다. 값이 설정되지 않는 오류를 컴파일 시점에 막아준다.
필수 필드인 memberRepository와 discountPolicy의 값을 설정하는 부분이 누락되었을 때 그냥 private을 사용하면 IDE에서 바로 알 수 없다.
값을 넣어주지 않아도 테스트 코드를 작성할 때까지 알 수가 없고 테스트를 실행하면 NullPointException이 나면서 값이 들어오지 않았다는 걸 알게된다.
final키워드를 사용하면 생성자에서 값이 설정되지 않는 오류를 컴파일 시점에 막아준다. (IDE에 바로 오류가 뜨기 때문에 빨리 발견할 수 있다.)