DI에는 생성자 기반
과 setter 기반
두가지 방식이 있다.
주로 필수 종속성에 대해서는 생성자 기반을 사용하고 선택적 종속성에 대해서는 setter 기반을 사용하는 것이 좋다.
public class SimpleMovieLister {
private final MovieFinder movieFinder;
public SimpleMovieLister(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
}
public class SimpleMovieLister {
private MovieFinder movieFinder;
private int i;
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
public void setIntegerProperty(int i)
{
this.i = i;
}
}
@Autowired
와 컴포넌트 스캔(@Compoment
, @Controller
, @Service
등) 어노테이션 사용@Service
public class SimpleMovieLister {
@Autowired
private MovieFinder movieFinder;
}
Spring에는 Bean을 생성하고 관리해주는 ApplicationContext
, BeanDefinition
이 존재한다.
ApplicationContext
는 관리되는 Bean에 대해 생성자 기반 및 setter 기반 DI를 지원한다.
하지만 Spring/Java 개발자는
@Component
, @Controller
등의 어노테이션을 통해 Bean 생성을 Spring에게 맡기고 ▶️ IoC
@Autowried
, @RequiredArgsConstructor
등의 어노테이션을 통해 쉽게 주입하여 사용하거나, 생성자 또는 setter 메서드를 통해 종속성을 주입하여 Bean을 사용할 수 있다. ▶️ DI
Spring 컨테이너는 컨테이너가 생성될 때 각 Bean의 구성을 검증하고 종속성(DI) 설정은 Bean이 실제 생성될 때 이루어진다.
이때 DI로 인해 주입되는 또다른 Bean은 이미 인스턴스화 된 객체로 이를 싱글톤 패턴이라고 한다.
생성자 기반 DI를 사용하는 경우 개발자는 순환 참조 발생을 주의해야한다.
주로 생성자 주입을 사용하는 경우 해결할 수 없는 순환 참조가 발생될 수 있다.
예를 들면 아래와 같이 A 생성자에서 B를 주입하려하고 B 생성자에서 A를 주입하려고 할 때, Spring IoC 컨테이너는 런타임에 인스턴스 순환 참조를 감지하고 BeanCurrentlyInCreationException
을 발생시킨다.
public class A {
private final B b;
public A (B b)
{
this.b = b;
}
}
public class B {
private final A a;
public B (A a)
{
this.a = a;
}
}
이 경우 해결책은 setter 메소드를 사용하도록 수정하는 것이다.
❓싱글톤 패턴
https://tecoble.techcourse.co.kr/post/2020-11-07-singleton/