스프링은 빈을 쭉 등록한 다음 의존관계 주입을 쭉 진행한다.
이렇게 두 가지 라이프사이클로 진행된다.
스프링 빈을 생성하는 단계와 의존관계를 주입하는 단계.
생성자 주입만 빈을 등록하면서 의존관계 주입도 같이 일어난다.
다른 주입은 두번째 단계에서 의존관계 주입이 일어난다.
Getter, setter가 필요 없다 —> 불변 의존관계
final이 붙으면 반드시 값이 존재해야한다. —> 필수 의존관계
생성자가 단 하나일 때는 @Autowired를 생략할 수 있다.
선택적으로 특정 값이 null이어도 가능하게한다 —> @Autowired(required = false)
특정 인스턴스를 바꾸고 싶다면 그냥 호출하면 되도록한다.
자바빈 프로퍼티 규약인 setter를 통한 주입이다.
필드 인젝션은 안 쓰는게 좋다. DI 프레임워크가 없으면 아무것도 못한다.
테스트 코드에서나 쓰자.
쓰지 말자.
사실상 수정자 주입이랑 똑같긴 하다. 그래서 쓸 일이 더 없다.
대부분의 의존관계는 애플리케이션 종료 전까지 변하면 안되기 때문이다.
생성자주입은 바뀌지 않는다.
수정자 주입은 set을 열어두어야 하기 때문에 실수로 바뀔 수 있다.
변경하면 안 되는 메서드 자체를 열어두는 게 좋은 설계가 아니다.
생성자는 딱 1번만 호출되므로 불변하게 설계할 수 있다.
생성자 주입을 쓰면 final 키워드를 넣을 수 있다는 장점이 있다.
final을 하면 무조건 생성자을 통해 할당이 되어야 한다.
final을 쓰면 한번 생성 되면 안 바뀐다. 그리고 값이 무조건 필요하다. 실수로 누락하는 걸 방지해 준다. 생성자에서 값이 설정되지 않는 오류를 컴파일 시점에 막아준다.
수정자 주입을 포함한 나머지 주입 방식은 모두 생성자 이후에 호출되어서 final키워드를 사용할 수 없다. 생성자 주입만 final 키워드를 사용할 수 있다.
프레임워크 없이 순수한 자바 코드를 단위 테스트 하는 경우에 좋다.
수정자 의존관계를 쓰면 테스트 코드를 짤 때 값을 세팅을 해야함
크리에이트 오더만 테스트하고 싶어도 가짜를 만들어서 넣어주어야 한다.
누락이 되버리는 것이다.
수정자 메서드를 두면 의존관계가 뭐가 들어가는지 안 보인다.
생성자 주입을 쓰면 의존관계가 뭐가 들어가는지 볼 수 있고 내 맘대로 구현체를 집어 넣을 수 있다.
프레임워크에 의존하지 않고 순수한 자바 언어의 특징을 살리는 방법이다.
기본으로 생성자 주입을 쓰고 필수값이 아닌 경우 수정자 주입 방식을 옵션으로 부여하면 된다.
개발 해 보면 대부분 불변성이 필요하다.
그래서 생성자에 final키워드를 사용하게 된다.
근데 생성자도 만들어야하고 주입받은 값을 대입하는 코드도 만들어야한다.
이걸 한 번에 해결해 주는 방법이 롬복이다.
롬복은 getter, setter, toString 등의 코드를 알아서 만들어 준다.
그 중에서도 스프링에서 많이 사용되는 것은 @RequiredArgsContructor이다.
@RequiredArgsContructor은 내 객체에 final이 붙은 변수를 파라미터로 받는 생성자를 만들어준다.
이는 대단한 기능이 된다.
왜냐.
최근에는 생성자를 딱 1개만 두고 @Autowired를 생략하는 방법을 주로 사용한다.
여기에 Lombok 라이브러리의 @RequiredArgsConstructor와 함께 사용하면 알아서 final이 붙은 변수를 파라미터로 받는 생성자를 만들어주기 때문에,
@Autowired가 생략된 생성자를 안보이게 만들어주는 것이 되므로,
기능은 다 제공되면서 코드는 깔끔한, 보이지 않는 생성자 주입을 사용할 수 있게 되는 것이다.
즉, 의존관계 주입과 Lombok은 엄청난 시너지가 나게 된다.
private final을 쓰니까 final을 사용하는 이점은 다 챙기면서 생성자 주입을 해 주기 때문에 생성자 주입으로 인한 이점을 다 챙기면서도 생성자가 하나만 있으면 @Autowired를 생략할 수 있다는 점을 이용해 Lombok을 써서 생성자까지 가려버려 모든 기능을 전부 다 제공하면서도 생성자는 가려버리는 깔끔한 코드가 완성되는 것이다.