spring boot로 코딩 중에, @Autowired를 사용할 때,
inteliJ warning에서
always use constructor based dependency injection in your beans. Always use assertions for mandatory dependencies
이런 메시지가 뜰 경우에,
@Autowired
private TestService testService;
위의 경우를
private final PodsService podsService;
public TestController(TestService testService) {
this.testService = testService;
}
다음과 같이 변경할 수 있습니다.
Spring 4.3부터는 Spring Bean으로 구성된 클래스가 오직 하나의 생성자를 가지면 Autowired 주석을 생략 할 수 있고 Spring은 해당 생성자를 사용하고 필요한 모든 의존성을 주입을 한다고 하네요.
DI도 디자인 패턴 중 하나이며, 의존성 주입이 코드 속에 숨겨질 경우, 의존하는 어떤 클래스가 문제가 생겼는지를 확인하기 위해서는 한번더 해당 클래스를 테스트해야하는 경우가 생깁니다.
Constructor DI 를 권장하는 이유는 다음과 같습니다.
-
단일 책임의 원칙 생성자의 인자가 많을 경우 코드량도 많아지고, 의존관계도 많아져 단일 책임의 원칙에 위배됩니다.
그래서 Constructor Injection을 사용함으로써 의존관계, 복잡성을 쉽게 알수 있어 리팩토링의 단초를 제공하게 됩니다. -
테스트 용이성 DI 컨테이너에서 관리되는 클래스는 특정 DI 컨테이너에 의존하지 않고 POJO여야 합니다.
DI 컨테이너를 사용하지 않고도 인스턴스화 할 수 있고, 단위 테스트도 가능하며, 다른 DI 프레임 워크로 전환할 수도 있게 됩니다. -
Immutability Constructor Injection에서는 필드는 final로 선언할 수 있습니다.
불변 객체가 가능한데 비해 Field Injection은 final는 선언할 수 없기 때문에 객체가 변경 가능한 상태가 된됩니다. -
순환 의존성 Constructor Injection에서는 멤버 객체가 순환 의존성을 가질 경우 BeanCurrentlyInCreationException이 발생해서 순환 의존성을 알 수 있게 된됩니다.
-
의존성 명시 의존 객체 중 필수는 Constructor Injection을 옵션인 경우는 Setter Injection을 활용할 수 있습니다.