3.3. Dependencies

3.3.1. Injecting dependencies

DI(Dependency Injection)이 적용되면 클래스들간의 관계에 고도의 디커플링을 유지할 수 있고 코드가 훨씬 깨끗해 집니다. 주로 setter injection과 constructor injection으로 나뉩니다.

Service Locater 패턴
참조.
Setter Injection & Constructor Injection

3.3.2. Constructor Argument Resolution

생성자의 인자를 구분 할 필요가 있는 경우에 인자의 type 또는 index로 구분할 수 있습니다.

Constructor Injection 할 때 인자 구분

3.3.3. Bean properties and constructor arguments detailed

<property /> 태그(=엘리먼트)와 <constructor-arg /> 태그는 종속성을 가지는 대상에 따라 사용할 수 있는 하위 태그들이 여러개 있습니다. ex. <value /> <idref /> <ref /> <bean />[footnote]inner bean[/footnote] <list /> <set /> <map /> <props /> <null />

idref 엘리먼트
Inner beans
Collections – <list />
Collection Merging

3.3.4. Using depends-on

<bean /> 태그의 depends-on 속성에 bean의 id를 적어주면 현재 bean을 초기화하기 전에 depends-on 속성에 적어준 bean들을 먼저 초기화 합니다.

<bean id=”beanOne” class=”ExampleBean” depends-on=”manager”/>

<bean id=”manager” class=”ManagerBean” />

위와 같이 설정 한다면 beanOne을 초기화 하기 전에 manager bean을 먼저 초기화 합니다.

만약 여러개의 bean에 종속성을 가지고 그 bean들이 먼저 초기화 되길 바란다면 아래 처럼 여러개를 적을 수 있습니다.

<bean id=”beanOne” class=”ExampleBean” depends-on=”manager,accountDao”>
  <property name=”manager” ref=”manager” />
</bean>

<bean id=”manager” class=”ManagerBean” />
<bean id=”accountDao” class=”x.y.jdbc.JdbcAccountDao” />


3.3.5. Lazily-instantiating beans

ApplicationContext를 구현한 container들은 모든 bean들을 기본적으로 singleton scope의 bean들을 pre-instantiation(초기 생성?) 합니다. [footnote]pre-instantiation은 container의 초기화 과정에서 객체를 생성하고 종속성을 설정하게 되는 것을 말합니다.[/footnote] 그렇게 함으로써 초기에 설정이나 기타 환경에 대한 에러들을 초기에 발견할 수 있습니다.

하지만~ 초기에 모든 bean들을 만들어 내기 싫을 수가 있는데요. 그럴 때는 <bean /> 태그에 lazy-init=”true” 를 추가하여 하나의 bean이 초기화 지연 기법을 사용할 수 있으며…
container의 기본 설정을 바꾸려면 configuration metadata의 최상위 엘리먼트인 <beans /> 태그에 default-lazy-init=”true” 를 추가하면 됩니다.

주의 : pre-instantiation bean이 lazy bean에 종속성을 가진다면..먼저 만들어야 할 bean 때문에 나중에 만들 bean도 먼저 만들게 됩니다.

3.3.6. Autowiring collaborators

bean들 간의 종속성을 자동으로 맺어 줄 수 있는 기능이 있습니다. 장단점을 알아봐야겠습니다.

Autowiring

3.3.7. Checking for dependencies

bean에 있는 모든 property들이 잘 세팅이 되었는지 확인하고 싶을 때 사용할 수 있습니다. <bean /> 태그에 dependency-check 속성에 네가지 모드 값 중에 하나를 선택에서 넣어주면 됩니다.

Mode Explanation
none

No dependency checking. Properties of the bean which
have no value specified for them are simply not set.

simple

Dependency checking is performed for primitive types
and collections (everything except collaborators, i.e. other
beans)

object

Dependency checking is performed for collaborators only

all

Dependency checking is done for collaborators, primitive types
and collections


3.3.8. Method Injection

singlton bean(매번 같은 객체) A가 non-singleton bean(매번 다른 객체) B를 사용하게 된다면(종속성을 가지면)…B는 의도 했던 바와는 다르게.. 매번 같은 객체만 사용될 것입니다.
 
이 문제를 해결 하는 방법으로는.. A가 BeanFactoryAware 인터페이스를 구현해서 B를 요구할 때마다 getBean(“B”)를 이용하는 방법이 있긴 한데…

이러면 A라는 클래스가 BeanFactoryAware라는 Spring Framework의 코드에 종속되기 때문에 Method Injection이라는 것을 사용해서 좀 더 깔끔하게 이 문제를 해결 할 수 있다고 합니다.

복잡한 Alias

사용자 삽입 이미지    <bean id=”혜인” name=”이쁘니” class=”beanConfiguration.Member”/>

    <alias name=”이쁘니” alias=”효도르” />
    <alias name=”이쁘니” alias=”지름쟁이” />

이 전 글에 이어서.. 이 상태에서 왠지 “지름쟁이”와 “효도르”로 얻어낸 bean은  “이쁘니”로 얻어낸 bean과 같을 것 같았는데… 다르네요.

        Member bean1 = (Member) bf.getBean(“혜인”);
        Member bean2 = (Member) bf.getBean(“이쁘니”);
        Member alias1 = (Member) bf.getBean(“효도르”);
        Member alias2 = (Member) bf.getBean(“지름쟁이”);

        assertFalse(bean2.equals(alias1));
        assertFalse(bean2.equals(alias2));

하지만 getAlias(“효도르”) 나 getAlias(“지름쟁이”)를 호출하게 되면 String 배열에는 “이쁘니”가 포함되어 있습니다. -_-;; 오.. 점점 혼란스러워 지는 군요.

“효도르”와 “지름쟁이”는 “이쁘니”의 Alias는 맞는데 “이쁘니”와 같은 객체는 아닙니다.

이렇게.. 복잡한 상황이 발 생할 수 있기 땜시..BeanDefinition 이름으로 alias를 설정해 주어야 합니다.

    <bean id=”혜인” name=”이쁘니” class=”beanConfiguration.Member”/>
    <alias name=”혜인” alias=”착한 아이” />
    <alias name=”혜인” alias=”얌전한 아이” />
사용자 삽입 이미지

    @Test public void beanDefinitionNameAliasing(){
        String[] aliases = bf.getAliases(“혜인”);
        assertTrue(aliases.length == 3);

        Member bean1 = (Member) bf.getBean(“혜인”);
        Member bean2 = (Member) bf.getBean(“이쁘니”);
        Member alias1 = (Member) bf.getBean(“착한 아이”);
        Member alias2 = (Member) bf.getBean(“얌전한 아이”);

        assertTrue(bean1.equals(bean2));
        assertTrue(bean1.equals(alias1));
        assertTrue(bean1.equals(alias2));
        assertTrue(alias1.equals(alias2));
    }

테스트는통과 합니다. 혜인이는 이쁘니, 착한 아이, 조용한 아이로 불러온 bean과 동일합니다.

String[] getAlias(String name) 이 메소드는 name에 혜인, 이쁘니, 착한 아이, 얌전한 아이를 넣으면 모두 자기 자신을 제외한 alias 3개씩을 가지게 됩니다.

“이쁘니”, “착한 아이”, “얌전한 아이”는 “혜인”의 alias이면서 “혜인”과 같은 객체입니다.