의존성 주입 Injecting Dependencies.
Dependency Injection(DI)의 가장 기본적인 원칙은 인스턴스의 생성자가 호출되거나 팩토리 메소드에서 인스턴스가 리턴된 후, 생성자의 인자나 팩토리 메소드의 인자를 통해서 받은 객체들과의 의존성 삽입이 다는 것 입니다. 매우 추상적이기는 하지만 DI를 적용할 때의 장점을 레페런스에서 간단히 언급하고 있습니다.
DI는 크게 두 가지 방법이 있습니다.
1. Setter Injection
빈의 생성 후 setter 메소드를 호출해서 의존성을 삽입하는 방법입니다.
생성자를 이용하는 방법입니다.
Constructor냐 Setter 냐?
스프링 팀의 의견은 일반적으로 setter injection이면 충분하다고 말하고 있습니다. 하지만 생성자를 이용한 방법도 몇 몇 purist(순수주의자^^)에 의해서 선호된다고 합니다. 그 이유는 setter 메소드를 클라이언트에게 공개하지 않아도 되기 때문입니다. 이 경우 객체를 다시 구성하기가 매우 까다로워 지는데, (레퍼런스의 표현 : less amenable to re-configuration, re-injection) 상황에 따라 장, 단점이 있을꺼라고 생각됩니다. 정해진 룰이나 답은 없죠~(no hard and fast Rule)
빈 의존성 주입 시에 무슨 일이 일어나나?
컨테이너가 생성될 때 스프링은 각 빈의 설정 정보와 속성들이 참조하고 있는 빈에 대한 유효성을 검증(validation) 합니다. 하지만 각 속성들에는 아직 실제 정보나 의존성이 주입된 것은 아닙니다. 이런 작업이 이루어지는 것은 실제 빈이 생성될 때 입니다. 만약 빈이 singleton-scope 이면서, pre-instantiated 상태라면 컨테이너가 생성될 때 실제 빈이 생성되는 작업이 수행됩니다.
빈에 대한 설정 정보와 구성 정보를 실제 생성하기 이전에 유효성을 검증한 다음에 실제 주입을 하는 작업은 가능한 늦게 수행하고 있습니다. 이런 작업을 통해서 실제 의존성을 주입하는 시점에서는 의존성 주입에 관한 정보 자체에 대한 신뢰성을 확보하려는 시도인 것 같습니다.
static factory method를 통해서 빈을 생성할 경우에는 의존성 주입에 관한 정보는 <constructor-args> 를 통해서 전달해 주면 됩니다.
Dependency Injection(DI)의 가장 기본적인 원칙은 인스턴스의 생성자가 호출되거나 팩토리 메소드에서 인스턴스가 리턴된 후, 생성자의 인자나 팩토리 메소드의 인자를 통해서 받은 객체들과의 의존성 삽입이 다는 것 입니다. 매우 추상적이기는 하지만 DI를 적용할 때의 장점을 레페런스에서 간단히 언급하고 있습니다.
- Much cleaner code
- higher grade of decoupling
- higher grade of decoupling
DI는 크게 두 가지 방법이 있습니다.
1. Setter Injection
빈의 생성 후 setter 메소드를 호출해서 의존성을 삽입하는 방법입니다.
2. Constructor Injectionpublic class SimpleMovieLister {
private MovieFinder movieFinder;
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
}
생성자를 이용하는 방법입니다.
public class SimpleMovieLister {
private MovieFinder movieFinder;
public SimpleMovieLister(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
}
Constructor냐 Setter 냐?
스프링 팀의 의견은 일반적으로 setter injection이면 충분하다고 말하고 있습니다. 하지만 생성자를 이용한 방법도 몇 몇 purist(순수주의자^^)에 의해서 선호된다고 합니다. 그 이유는 setter 메소드를 클라이언트에게 공개하지 않아도 되기 때문입니다. 이 경우 객체를 다시 구성하기가 매우 까다로워 지는데, (레퍼런스의 표현 : less amenable to re-configuration, re-injection) 상황에 따라 장, 단점이 있을꺼라고 생각됩니다. 정해진 룰이나 답은 없죠~(no hard and fast Rule)
빈 의존성 주입 시에 무슨 일이 일어나나?
1. BeanFactory(ApplicationContext)가 모든 빈을 초기화합니다.
2. 빈의 의존성은 properties 형태나, 생성자의 인자, static-factory 메소드의 인자 등으로 받아올 수 있습니다. 이러한 의존성은 실제 빈이 생성될 때 빈에게 주입되게 됩니다.
3. 각 속성이나 생성자 인자는 실제 값이거나 컨테이너 내에 있는 또 다른 빈의 참조 값입니다.
4. 스프링에서 제공되는 PropertyEditor에 의해서 각 속성이나 생성자 인자가 갖는 실제 타입으로 변경됩니다.
2. 빈의 의존성은 properties 형태나, 생성자의 인자, static-factory 메소드의 인자 등으로 받아올 수 있습니다. 이러한 의존성은 실제 빈이 생성될 때 빈에게 주입되게 됩니다.
3. 각 속성이나 생성자 인자는 실제 값이거나 컨테이너 내에 있는 또 다른 빈의 참조 값입니다.
4. 스프링에서 제공되는 PropertyEditor에 의해서 각 속성이나 생성자 인자가 갖는 실제 타입으로 변경됩니다.
컨테이너가 생성될 때 스프링은 각 빈의 설정 정보와 속성들이 참조하고 있는 빈에 대한 유효성을 검증(validation) 합니다. 하지만 각 속성들에는 아직 실제 정보나 의존성이 주입된 것은 아닙니다. 이런 작업이 이루어지는 것은 실제 빈이 생성될 때 입니다. 만약 빈이 singleton-scope 이면서, pre-instantiated 상태라면 컨테이너가 생성될 때 실제 빈이 생성되는 작업이 수행됩니다.
빈에 대한 설정 정보와 구성 정보를 실제 생성하기 이전에 유효성을 검증한 다음에 실제 주입을 하는 작업은 가능한 늦게 수행하고 있습니다. 이런 작업을 통해서 실제 의존성을 주입하는 시점에서는 의존성 주입에 관한 정보 자체에 대한 신뢰성을 확보하려는 시도인 것 같습니다.
상호참조.
두 개의 인스턴스가 상호 참조 하고 있는 경우 생성자를 통한 의존성 주입일 할 때 BeanCurrentlyCreationException이 발생합니다. 해결책을 두 가지 제시하고 있는데요, 결국 요즘은 이럴 경우에는 setter injection을 사용하라는 것 입니다.
두 개의 인스턴스가 상호 참조 하고 있는 경우 생성자를 통한 의존성 주입일 할 때 BeanCurrentlyCreationException이 발생합니다. 해결책을 두 가지 제시하고 있는데요, 결국 요즘은 이럴 경우에는 setter injection을 사용하라는 것 입니다.
static factory method를 통해서 빈을 생성할 경우에는 의존성 주입에 관한 정보는 <constructor-args> 를 통해서 전달해 주면 됩니다.
<bean id="exampleBean" class="examples.ExampleBean"
factory-method="createInstance">
<constructor-arg ref="anotherExampleBean"/>
<constructor-arg ref="yetAnotherBean"/>
<constructor-arg value="1"/>
</bean>
<bean id="anotherExampleBean" class="examples.AnotherBean"/>
<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>

Prev

Rss Feed