2009년 04월 14일
Spring의 컨테이너 ..
DI가 소프트웨어 컴포넌트의 결합도를 낮춰 준다면, 애스펙트 지향 프로그래밍은 애플리케이션 전체에 걸쳐 사용되는 기능을 재사용할 수 있는 컴포넌트에 담을 수 있게 해 준다.
스프링을 컨테이너라고 하는데, 단지 객체의 자원을 관리해주는 역활이라고 생각하고 있었다.
하지만 보다 명확히 살펴보면
스프링의 컨테이너에도 종류가 있다.
디자인 패턴 중 팩토리 패턴을 구현하여 빈의 생명주기를 관리하는 책임을 가진 클래스가 다.
그리고 팩토리 컨테이너의 한계를 더 넓혀 다음의 3가지 기능을 추가로 제공해주는 애플리케이션 컨텍스트가 있다.
1. 국제화가 지원되는 텍스트 메시지를 관리해 준다.
2. 이미지 같은 파일 자원을 로드 할 수 있는 포괄적인 방법을 제공해 준다.
3. 리스너로 등록된 빈에게 이벤트 발생을 알려 준다.
이와 같은 추가 기능 때문에, 대부분의 애플리케이션에서는 BeanFactory보다 Applicationcontext를 사용하는 것이 좋다. BeanFactory를 추천할 만한 상황은 사실 모바일 장치 같은 하드웨어 리소스가 빈약한 환경일 때뿐이다.
ApplicationContext 구현체 중 가장 많이 사용되는 클래스는 다음과 같다.
1. ClassPathXmlApplicationContext - 클래스 패스에 위치한 XML 파일에서 컨텍스트 정의내용을 읽어들인다.
2. FileSystemXmlApplicationContext - 파일 시스템에서, 즉 파일 경로로 지정된 XML파일에서 컨텍스트 정의내용을 읽어들인다.
3. XmlWebApplicationContext - 웹 어플리케이션에 포함된 XML 파일에서 컨텍스트 정의내용을 읽어들인다.
* ApplicationContext 인터페이스는 BeanFactory를 확장하였다.
추가 기능을 제공하는 것 말고도 애플리케이션 컨텍스트는 빈팩토리와 큰 차이점이 하나 있는데, 싱글톤 빈을 로드하는 방식이 서로 다르다는 점이다. 빈 팩토리는 처음으로 getBean()이 호출된 시점에서야 해당 빈을 생성하 데 비해, 애플리케이션 컨텍스트는 좀 더 영리하게 컨텍스트 초기화 시점에 모든 싱글톤 빈을 미리 로드해 둔다. 싱글톤 빈을 미리 로드해 둠으로써 애플리케이션 기동 후에는 빈을 지연 없이 얻을 수 있다.
- 빈의 일생에서 일어나는 과정(팩토리빈)
1. 인스턴스화 : 스프링이 빈을 인스턴스화 한다.
2. 프로퍼티 할당 : 스프링이 빈의 프로퍼티 값을 주입한다.
3. 빈의 이름을 알려 줌 : 빈이 BeanNameAware 인터페이스를 구현하면 스프링이 빈의 setBeanName을 호출해서 ID를 알린다.
... 테스트 해봤는데 BeanNameWare를 implements 한 클래스에 abstract 메서드인 setBeanName을 구현하고
해당 setter내에서 System.out.println arg0 해봐두 null로 뜨더라
그래서 이건 무시하기로 했고
단지 팩토리빈과 Application빈의 차이는 setBeanFactory - BeanPostProcessor 사이에 setApplicationContext라는 과정이 하나더 추가된다는 정도만 알고 넘어가자.
기존에는 클래스안에서 선언된 beanid에만 객체 주입이 되는 줄 알았는데
ApplicationContext.xml내에서도
다른 Beanid가 인스턴스화하기위한 파라미터(이를테면 생성자의 파라미터로) xml에 선언된 다른 Beanid를 참조 할 수 있다
아래의 코드는 그 예이다.
<bean id ="duke" class="com.springinaction.springidol.PoeticJuggler">
<construcor-arg value="15" />
<constructor-arg ref="sonnet29" />
</bean>
- 생성자 주입 방식이냐 세터 주입 방식이냐
1. 생성자 주입 방식은 강력한 의존성 규약의 준수를 강제한다.(무결성을 강조 할 수 있다.)
- 쓸때 없는 세터 메서드가 사라진다.
- 스프링은 XML로 지정된 값을 프로퍼티의 타입에 따라 알아서 변환한다(모든건 기본적으로 String으로 선언)
Perfomer performer = (Performer) ctx.getBean("kenny"); 에서
굵게 표시한 저런 부분을(명시적 캐스팅) 개인적으로 거부감이 있었는데 Spring에서는 추천하는 부분이다.
인터페이스가 DI에 힘을보태어 (loose coupling)을 달성한다.
내부 클래스(inner class)라는것과 유사한 내부 빈(inner beans)라는 스프링 테크닉이 있다.
아래의 코드로 걍 정리
<bean id ="duke" class="com.springinaction.springidol.PoeticJuggler">
<constructor-arg value="15" />
<property name="instrument">
<bean class="org.springinaction.springidol.saxphone" />
</property>
<constructor-arg>
<bean class="com.springinaction.springidol.Sonnet29" />
</constructor-arg>
</bean>
눈여겨볼 건 내부 빈에는 id 애트리뷰트가 없다는 것이다.
지금 까지는 파라미터로 단수만 사용했는데, 복수로도 사용가능하다.
스프링에서는 총 4가지의 컬렉션 엘리먼트를 지원한다.
<list>와 <set> 엘리먼트는, 배열 타입이나 java.util.Collection 타입의 프로퍼티를 설정할 때 쓰인다.
두 엘리먼트 모두 java.util.Collection 타입의 프로퍼티에 사용 가능하다.
- 자바가 가진 다양한 컬렉션 타입을 지원하는 Spring
1. <list> : 값의 리스트에 사용, 중복 허용
2. <set> : 값의 집합에 사용. 중복 없음 보장
3. <map> : 키-값 쌍의 컬렉션에 사용, 키와 값은 아무 타입이나 가능
4. <props> : 키-값 쌍의 컬렉션에 사용, 키와 값이 모두 String
<map>과 <props> 엘리먼트는 각기 java.util.Map과 java.util.Properties에 해당한다. 이 두 가지 컬렉션은 키 -값 쌍으로 만들어진 컬렉션이 필요할 때 유용한다.
걍 코드로 말하자. ㅋ
<bean id ="duke" class="com.springinaction.springidol.PoeticJuggler">
<constructor-arg value="15" />
<property name="instrument">
<list>
<ref bean="guitar" />
<ref bean="cymbal" />
</list>
</property>
</bean>
맵 타입으로 바꾸기
<bean id ="duke" class="com.springinaction.springidol.PoeticJuggler">
<constructor-arg value="15" />
<property name="instrument">
<map>
<entry key="GUITAR" value-ref="guitar" />
<entry key="CYMBAL" value-ref="cymbal" />
<entry key="HARMONICA" value-ref="harmonica" />
</map>
</property>
</bean>
<map>의 <entry>는 키와 값으로 구성된다. 각각은 원시형일 수도 있고, 다른 빈에 대한 레퍼런스일 수도 있다.
1. key : 맵 엔트리의 키를 String 값으로 지정하고자 할 때
2. key-ref : 맵 엔트리의 키를 스프링 컨텍스트 내의 다른 빈으로 지정하고자 할 때
3. value : 맵 엔트리의 값을 String 값으로 지정하고자 할 때
4. value-ref : 맵 엔트리의 값을 스프링 컨텍스트 내의 다른 빈으로 지정하고자 할 때
<props>는 무조건 키와 값을 String으로 사용해야 한다.
-java.util.Properties 를 사용하는 <props> 사용법
<bean id ="duke" class="com.springinaction.springidol.PoeticJuggler">
<constructor-arg value="15" />
<property name="instrument">
<props>
<prop key="GUITAR" >guitar" </prop>
</props>
</property>
</bean>
* 어떤 빈에 명시적으로 'null'을 주고 싶으면 다음과 같이 사용한다
<property name="someNonNullProperty "><null/></property>
명시적으로 null을 사용해야 하는 경우 중 하나느 오토와이어링(autowiring)을 사용할 때 다.
네 종류의 오토와이어링을 지원한다.
1. byName - 프로퍼티 명과 같은 이름의 빈을 컨테이너에서 찾는다.
2. byType - 프로퍼티가 가진 타입에 맞는 유일한 빈을 컨테이너에서 찾는다. , 만약 둘 이상의 빈이 해당되면
UnsatisfiedDependencyException을 발생시킨다.
3. constructor - byType과 유사하지만 생성자용 버전이다.
4. autodetect - 기본생성자가 정의되어 있으면 byType이 적용된다. 기본 생성자가 없는 경우 constructor를 적용한다.
빈이 인스턴스화 된 후- 그리고 종료 전에 어떤 메소드를 호출 하고 싶다면 init-method와 destroy-method를 사용한다.
그리고 유효 범위를 지정 할 수 있는 scope 라는 인자가 생겼다 이것은 스프링 2.0에서 명시적으로 새로운 유효범위를 나타내기 위해서 만들어졌다. 따라서 Spring 1.x에는 지원안된다.
<bean id ="duke" class="com.springinaction.springidol.PoeticJuggler" init-method="tuneInstrument" destroy-method="cleanInstrument" scope="prototype" >
<constructor-arg value="15" />
<property name="instrument">
<props>
<prop key="GUITAR" >guitar" </prop>
</props>
</property>
</bean>
모든 빈에 init-method와 destroy-method를 지정 할 수 있다.
<beans default-autowire="byName" default-init-method="" default-destroy-method="" >
</beans>
또한 InitializingBean 과 DisposableBean을 Implements 해두 된다.
(단점은 의존성이 생긴다)
jar 파일을 교체하고 나서 해결
그리고 무엇보다 중요한것은 2.0 스키마로 ApplicationContext 파일을 변경할 경우,
기존 1.0 스키마에서 사용하던 Singleton="true"와 같은 엘리먼트 이름이 사라졌다는 것이다.
기존 1.0스키마에서 사용하던 Singleton="true" --> scope="singleton" 과 같으며, singleton="false" 는 scope="prototype"과 같다고 소개되어있다.
테스트중.. 완료
ApplicationContext.xml 의 아래의 스키마를
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans default-autowire="byName" >
스프링 2.x 규약에 맞게 바꾸면
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd" default-autowire="byName">
와 같으며
기존 아래의 구문은
<bean id="baseAction" class="com.jce.searchengine.common.action.BaseAction" autowire="byName" singleton="false" />
다음과 같이 바뀐다.
<bean id="baseAction" class="com.jce.searchengine.common.action.BaseAction" autowire="byName" scope="prototype" />
-기본 와이어링 방법 끝
# by | 2009/04/14 22:36 | 트랙백 | 덧글(0)








☞ 내 이글루에 이 글과 관련된 글 쓰기 (트랙백 보내기) [도움말]