'Dependency Injection'에 해당되는 글 2건
- 2009/08/06 Dependency Indejection 표준 정하기 논쟁
- 2007/04/23 Injecting dependencies
놀세 님의 블로그에서 흥미로운 글을 하나 읽었습니다.
당연한 일인데 말이죠..
놀세님의 블로그에 나오듯이 jsr-330은 아직 걸음마 수준인데 반해, jsr-299는 상당히 진전이 된 상태이고, 이번 java one에서도 jee 6 관련 세션으로 진행까지고 하고 있습니다.
진행 상황만 보면 사실 jsr-299가 한창 차리고 있는 상을 뒤늦게 한 친구(jsr-330)가 나타나 상 앞에 앉아서 맛있는 반찬 그릇을 자기 앞으로 가지고 가려는 듯 보입니다. 내부에 어떤 히스토리가 더 있겠는지는 모르겠지만요..
방금 전에 올라온 인포 큐에는 이에 대한 다양한 사람과 투표자(voter)들의 코멘트가 올라왔는데, 역시 gavin은
여기까지는 분위기고, 중요한건 두 친구들의 표준 수립이 어떤 모양으로 되어 있고, 지향하는 바가 무엇인지를 한 번 살펴봐야 여기서 하는 얘기들에 공감을 할 수 있을 것 같습니다.
다음번에는 양쪽 내용을 한 번 살펴보도록 하겠습니다.
Seam(JSR-299)과 Spring(JSR-330)의 만남gavin king이 jsr-299을 진행하고 있고(얼마전에는 이름도 변경했던 것죠..), spring과 google guice가 손을 잡았다는 기사도 봤었는데, 그 기사만 보고 지나갔지 이런 흥미로운 일들이 일을 생각해보지는 못했습니다^^;
당연한 일인데 말이죠..
놀세님의 블로그에 나오듯이 jsr-330은 아직 걸음마 수준인데 반해, jsr-299는 상당히 진전이 된 상태이고, 이번 java one에서도 jee 6 관련 세션으로 진행까지고 하고 있습니다.
진행 상황만 보면 사실 jsr-299가 한창 차리고 있는 상을 뒤늦게 한 친구(jsr-330)가 나타나 상 앞에 앉아서 맛있는 반찬 그릇을 자기 앞으로 가지고 가려는 듯 보입니다. 내부에 어떤 히스토리가 더 있겠는지는 모르겠지만요..
방금 전에 올라온 인포 큐에는 이에 대한 다양한 사람과 투표자(voter)들의 코멘트가 올라왔는데, 역시 gavin은
I think it would be a huge mistake to introduce a second set of annotations which are semantically identical to those in 299 and address the exactly the same problem - gavin그리고 Antonio Goncalves란 분은 약간 우회적으로 현 상황을 표현해주기도 하셨습니다.
I hope we are not starting a new battle like the one between Java Module (JSR 277), Modularity Support (JSR 294) - Antonio음..일단 전반적인 분위기는 이렇습니다.
여기까지는 분위기고, 중요한건 두 친구들의 표준 수립이 어떤 모양으로 되어 있고, 지향하는 바가 무엇인지를 한 번 살펴봐야 여기서 하는 얘기들에 공감을 할 수 있을 것 같습니다.
다음번에는 양쪽 내용을 한 번 살펴보도록 하겠습니다.
의존성 주입 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