생성자 주입을 하며 final 키워드를 빼먹은 채 하루를 날린 나 자신...반성하며 이 포스트를 작성합니다.
스프링에서는 객체의 생성과 소멸 등에 대한 제어를 컨테이너가 관리하고 필요할 때 주입을 받아 사용한다.
본 포스트는 스프링 부트 기준으로 작성되었습니다. 스프링 과는 다른점이 있을 수 있습니다.
자동차를 만든다고 상상해봅시다.
자동차에는 엔진, 타이어, 스티어링 휠과 같은 다양한 부품들이 존재하고 있습니다. 이러한 부품들은 Sping 애플리케이션의 빈과 같습니다.
위 부품들에는 엔진=연료, 타이어=공기, 스티어링 휠=운전자 와 같이 특정 리소스가 필요하다고 가정하고 의존성 주입을 사용하지 않으면 각 구성요를 수동으로 조립하고 필요한 리소스를 제공해야합니다.
또한 각 구성요소가 올바른 리소스에 연결되어 있는지 확인도 해줘야 합니다.
의존성 주입을 사용하게 되면 필요한 리소스를 각 구성요소에 주입 할 수 있습니다.
이 느슨한 결합은 코드를 더 모듈화하고 유연하며 이해하기 쉽게 만들어 줍니다.
좀 더 이해를 돕기위해 그림을 첨부해보았습니다.
표준 Spring 프레임워크 기법 중 어떤 것이든 자유롭게 사용하여 빈과 주입된 종속성을 정의할 수 있습니다.
일반적으로 생성자 주입을 사용하여 종속성을 연결하고 @ComponentScan을 사용하여 빈을 찾는 것을 권장합니다.
public class SimpleMovieLister {
// SimpleMovieLister는 MovieFinder에 의존한다.
private final MovieFinder movieFinder;
// Spring 컨테이너가 MovieFinder를 주입할 수 있는 생성자
public SimpleMovieLister(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
// 주입된 MovieFinder를 실제로 사용하는 비즈니스 로직은 생략...
}
위 예제는 생성자 주입을 사용하여 필수 MovieFinder
빈을 가져오는 SImpleMovieLister
를 보여줍니다.
생성자 주입을 사용하면 MovieFinder
필드를 final
로 표시하여 나중에 변경 할 수 없음을 나타낼 수 있습니다.
빈에 생성자가 두 개 이상 있는 경우 Spring에서 사용할 생성자를 @Autowired
로 표시해야 합니다:
public class SimpleMovieLister {
private MovieFinder movieFinder;
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
// 비즈니스 로직 생략...
}
setter 기반 주입은 인수가 없는 생성자 또는 인수가 없는 static
팩토리 메서드를 호출하여 Bean을 인스턴스화한 후 빈에서 setter 메서드를 호출하는 컨테이너에 의해 수행됩니다.
public class SimpleMovieLister {
@Autowired
private MovieFinder movieFinder;
// 비즈니스 로직 생략...
}
컨텍스트와 개발자의 기본 설정에 따라 다릅니다.
생성자 주입
은 개체가 생성될 때 필요한 모든 종속성이 존재하도록 보장하기 때문에 일반적으로 모범 사례로 간주됩니다.
또한 클래스의 종속성을 이해하고 테스트 가능성을 개선하는 데 도움이 될 수 있는 종속성을 명시적으로 만듭니다.
Setter 주입
은 설정할 수 있는 여러 종속성이 있거나 일부 종속성이 선택적일 때 유용합니다.
필드 주입
은 가장 간단한 방법이지만 몇 가지 단점이 있습니다.
이는 클래스 간의 긴밀한 결합으로 이어져 테스트를 더 어렵게 만들 수 있습니다.
또한 명시적으로 선언되지 않았기 때문에 종속성을 식별하기가 더 어려워질 수 있습니다.
전반적으로 응용 프로그램의 특정 컨텍스트 및 요구 사항에 따라 사용할 주입 방법을 결정하는 것은 개발자의 몫입니다.
생성자 기반 또는 세터 기반 DI?
생성자 기반 DI와 세터 기반 DI를 혼합할 수 있으므로 필수 종속성에 대해서는 생성자를 사용하고 선택적 종속성에 대해서는 세터 메서드 또는 구성 메서드를 사용하는 것이 좋습니다. setter 메서드에서 @Autowired 주석을 사용하여 속성을 필수 종속성으로 만들 수 있습니다. 그러나 프로그래밍 방식으로 인수를 검증하는 생성자 주입이 더 좋습니다.Spring 팀은 일반적으로 생성자 주입을 옹호하는데, 이는 애플리케이션 구성 요소를 불변 객체로 구현하고 필수 종속성이
null
. 또한 생성자 주입 구성 요소는 항상 완전히 초기화된 상태로 클라이언트(호출) 코드에 반환됩니다. 참고로 많은 수의 생성자 인수는 나쁜 코드 냄새입니다. 즉, 클래스에 너무 많은 책임이 있을 수 있으며 문제의 적절한 분리를 더 잘 해결하기 위해 리팩토링해야 합니다.세터 주입은 기본적으로 클래스 내에서 합리적인 기본값을 할당할 수 있는 선택적 종속성에만 사용해야 합니다. 그렇지 않으면 코드가 종속성을 사용하는 모든 곳에서 null이 아닌 검사를 수행해야 합니다. setter 주입의 한 가지 이점은 setter 메서드가 해당 클래스의 개체를 나중에 재구성하거나 다시 주입할 수 있도록 만든다는 것입니다. 따라서 JMX MBeans를 통한 관리는 세터 주입에 대한 강력한 사용 사례입니다.
특정 클래스에 가장 적합한 DI 스타일을 사용하십시오. 때로는 소스가 없는 타사 클래스를 처리할 때 선택이 이루어집니다.
예를 들어 타사 클래스가 setter 메서드를 노출하지 않는 경우 생성자 주입이 유일하게 사용 가능한 DI 형식일 수 있습니다.
https://girawhale.tistory.com/113
https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-dependencies