Basic

Container와 Bean

Bean은 Spring Framework에서 어플리케이션의 중요 부분을 형성하고 Spring IoC Container에 의해 관리된다.
  • Bean 설정, 생성, Life Cycle 관리
  • Bean Wiring(엮기) - Bean들과 각각에 대한 Dependency 관계는 Spring IoC Container에 의해 사용되는 설정 메타데이터로 반영

Container

    Spring IoC Container

    Spring IoC Container는 다음 두 가지 유형의 Container 제공한다.
    • BeanFactory
      설 명
      Bean의 생성과 소멸 담당
      Bean을 생성 시 필요한 속성 설정
      Bean의 Life Cycle에 관련된 메소드 호출
      다수의 BeanFactory 인터페이스 구현 클래스를 제공하며 이중 가장 유용한 것은 XmlBeanFactory임
    • ApplicationContext
      설 명
      BeanFactory의 모든 기능 제공
      ResourceBundle 파일을 이용한 국제화(I18N) 지원
      다양한 Resource 로딩 방법 제공
      이벤트 핸들링
      Context 시작 시 모든 Singleton Bean을 미리 로딩(preloading) 시킴-> 초기에 설정 및 환경에 대한 에러 발견 가능함
      다수의 ApplicationContext 구현 클래스 제공(XmlWebApplicationContext,FileSystemXmlApplicationContext,ClassPathXmlApplicationContext)


    org.springframework.beans 와 org.springframework.context 패키지가 Spring Framework의 IoC Container를 위한 기본을 제공한다. BeanFactory는 객체를 관리하는 고급 설정 기법 제공하고 ApplicationContext는 Spring의 AOP기능, 메시지 자원 핸들링, 이벤트 위임, 웹 어플리케이션에서 사용하기 위한 WebApplicationContext와 같은 특정 어플리케이션 컨텍스트를 이용한 용이한 통합과 같은 다른 기능을 추가 제공한다. 즉, BeanFactory가 설정 프레임워크와 기본 기능을 제공하는 반면 ApplicationContext는 BeanFactory의 모든 기능 뿐 아니라 전사적 중심의 기능이 추가되어 있다. ApplicationContext가 제공하는 부가 기능과는 별개로, ApplicationContext와 BeanFactory의 또 다른 차이점은 Singleton Bean을 로딩하는 방법에 있다. BeanFactory는 getBean() 메소드가 호출될 때까지 Bean의 생성을 미룬다. 즉 BeanFactory는 모든 Bean을 늦게 로딩(Lazy loading)한다. ApplicationContext는 Context를 시작시킬 때 모든 Singleton Bean을 미리 로딩함으로써, 그 Bean이 필요할 때 즉시 사용될 수 있도록 보장해준다. 즉, 어플리케이션 동작 시 Bean이 생성되기를 기다릴 필요가 없다.
    • BeanFactory
    • Bean을 포함하고 관리하는 책임을 지는 Spring IoC Container의 실제 표현이다.가장 공통적으로 사용되는 BeanFactory의 구현체인 XmlBeanFactory 클래스는 XML로 애플리케이션과 객체간의 참조 관계를 조합하는 객체를 표시함으로써 XML 설정 메타데이터를 가지고 완전히 설정된 시스템이나 애플리케이션을 생성한다.
      또한 아래의 예와 같이 XmlBeanFactory는 XML 파일에 기술되어 있는 정의를 바탕으로 Bean을 Loading해준다. (생성자에 org.springframework.core.io.Resource타입의 객체 넘겨줌)
      BeanFactory factory = new XmlBeanFactory(new FileInputStream("beans.xml”));
      org.springframework.beans.factory.BeanFactory인터페이스에 관한 API는 여기 를 참고한다.
      Resource Implementation
      Purpose
      org.springframework.core.io.ByteArrayResource Defines a resource whose content is given by an array of bytes
      org.springframework.core.io.ClassPathResource Defines a resource that is to be retrieved from the classpath
      org.springframework.core.io.DescriptiveResource Defines a resource that holds a resource description but no actual readable resource
      org.springframework.core.io.FileSystemResource Defines a resource that is to be retrieved from the file system
      org.springframework.core.io.InputStreamResource Defines a resource that is to be retrieved from an input stream
      org.springframework.web.portlet.context.PortletContextResource Defines a resource that is available in a portlet context
      org.springframework.web.context.support.ServletContextResource Defines a resource that is available in a servlet context
      org.springframework.core.io.UrlResource Defines a resource that is to be retrieved from a given URL
    • ApplicationContext
    • 다음은 org.springframework.context.ApplicationContext 인터페이스의 대략적인 구조이다.

      자주 사용되는 ApplicationContext 구현 클래스는 아래와 같다.
      • XmlWebApplicationContext - 웹 기반의 Spring 애플리케이션을 작성할 때 내부적으로 사용
      • FileSystemXmlApplicationContext - 파일 시스템에 위치한 XML 설정 파일을 읽어들이는 ApplicationContext
      • ClassPathXmlApplicationContext - 클래스 패스에 위치한 XML 설정 파일을 읽어들이는 ApplicationContext
      ApplicationContext 구현 클래스를 아래와 같이 사용할 수 있다.
      ApplicationContext context =  new FileSystemXmlApplicationContext("c:/foo.xml”);
      ApplicationContext context = new ClassPathXmlApplicationContext("foo.xml”);
    • 설정 메타데이터
    • Container에 "인스턴스화, 설정, 그리고 조합[어플리케이션내 객체를]”하는 방법을 알려준다. 대부분은 간단하고 직관적인 XML 형태로 제공되며 XML 기반의 설정 메타데이터를 사용하여 Bean을 정의하도록 한다. 다음은 XML 기반의 설정 메타데이터의 기본 구조 예제이다.
      <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.5.xsd">
        <bean id="..." class="...">
          <!-- collaborators and configuration for this bean go here -->
        </bean>
      <!-- more bean definitions go here... -->
      </beans>

      XML 기반의 메타데이터는 설정 메타데이터의 가장 많이 사용되는 형태이다. XML 외에 Java Properties 파일을 이용하거나 프로그램으로 처리(Spring의 Public API를 사용하여)하는 설정 메타데이터를 제공할 수 있다. Spring IoC Container 자체는 설정 메타데이터의 형태로부터 분리될 수 있기 때문이다.
    • Spring IoC Container 인스턴스화 시키는 예제
    • Resource resource = new FileSystemResource("beans.xml");
      BeanFactory factory = new XmlBeanFactory(resource);
      ClassPathResource resource = new ClassPathResource("beans.xml");
      BeanFactory factory = new XmlBeanFactory(resource);
      ApplicationContext context = new ClassPathXmlApplicationContext(
      	new String[] {"applicationContext.xml", "applicationContext-part2.xml"});
      // of course, an ApplicationContext is just a BeanFactory
      BeanFactory factory = (BeanFactory) context;
    • XML 기반 설정 메타데이터 조합
    • XML 기반 설정 메타데이터 조합으로 Bean 정의를 다중 XML파일로 분리 할수 있다. 여기서 주의할 점은 <import/> 요소를 import를 수행하는 파일에서 <bean/> 요소이전에 두어야만 하는 것이다.
      <beans>
      	<import resource="services.xml"/>
      	<import resource="resources/messageSource.xml"/>
      	<import resource="/resources/themeSource.xml"/>
      
      	<bean id="bean1" class="..."/>
      	<bean id="bean2" class="..."/>
      </beans>
      위의 예제에서 외부 Bean정의는 3개의 파일(services.xml, messageSource.xml, 과 themeSource.xml)로부터 로드된다. 모든 위치 경로는 import를 수행하는 정의파일에 상대적이다. 그래서 이 경우에 messageSource.xml 과 themeSource.xml이 import파일의 위치 아래의 resources 에 두어야 하는 반면에 services.xml은 import를 수행하는 파일과 같은 디렉토리나 클래스패스 경로 내에 두어야만 한다. 이 예제처럼 /는 실제로 무시된다. import된 파일의 내용은 <beans/>요소를 가장 상위 레벨에 포함하는 스키마나 DTD에 따라 완전히 유효한 XML bean정의 파일이어야만 한다.

Beans

    Bean

    Spring IoC Container에 의해 관리되는 객체로 Container에 제공된 설정 메타데이터 내 정의(대개 XML <bean/> 정의의 형태로)에 의해 생성되며 실제로 아래 표로 나타낸 메타데이터 정보를 포함하는 BeanDefinition 객체로 표현한다.
    주요 메타데이터 속성
    설 명
    id Bean의 구분을 위한 정보로 해당 bean에 접근하기 위한 Key임
    class 정의된 Bean의 실제 구현클래스로 항상 full name으로 작성
    singleton true/false 값을 가지며 해당 bean을 singleton으로 유지할 것인지 여부를 결정함. Default는 true이며 false일 경우, getBean() 메소드 사용하여 사용할 때 마다 해당 bean 객체 생성됨
    init-method 해당 bean이 초기화된 후 context에 저장되기 전 호출되는 초기화 메소드 정의
    destroy-method 해당 bean 제거 시 호출되는 메소드 정의
    factory-method 해당 bean 생성 시 생성자를 사용하지 않고 특정 factory method를 호출하여 생성 시 정의
    lazy-init true/false 값을 가지며 해당 bean이 호출되기 전에 초기화 시킬지 여부를 결정함. Default는 false이며 true인 경우, 해당 bean이 호출되는 시점에 초기화시킴

    Bean 명명하기

    Bean 정의 시 Bean들을 구분하기 위해 ‘id’ 혹은 ‘name’ 속성을 사용하는데 ‘id’를 사용하는 경우, 하나의 Bean은 Container내에서 Unique한 id를 가지도록 한다.Bean을 명명할때 인스턴스 필드명의 표준 Java 규칙을 사용한다. Bean 이름은 소문자로 시작하고 camel-cased(첫 번째 단어는 소문자로 시작하고 두 번째 단어는 대문자로 시작)된다. 이러한 이름의 예제는 ‘accountService', 'userDao', 'loginController' 등이다. Bean을 명명하는 일관적인 방법을 적용하는 것은 설정을 좀더 읽기 쉽고 이해하기 쉽도록 만들어준다. 이러한 명명표준을 적용하는 것은 어려운 일이 아니다. Spring AOP를 사용한다면 이름에 관련된 Bean의 세트에 advice를 적용할 때 용이해질 수 있다.

    Bean 인스턴스화 (3가지 방법 제시)

    • 생성자를 이용한 인스턴스화
    • 특정 인터페이스를 구현하거나 특정 형태로 코딩 할 필요가 없다.
      <bean id="exampleBean" class="examples.ExampleBean"/>
      <bean name="anotherExample" class="examples.ExampleBeanTwo"/>
    • static factory 메소드를 사용한 인스턴스화
    • Bean 객체가 factory 메소드를 호출하여 생성되는 것으로, 반환 객체의 타입을 명시하지 않고 factory 메소드를 포함하는 클래스를 정의하고 있음에 주의한다. 아래 예제에서 createInstance() 메소드는 static 메소드이어야 한다.
      <bean id="exampleBean" class="examples.ExampleBean2" factory-method="createInstance"/>
    • 인스턴스 factory 메소드를 사용한 인스턴스화
    • 'class' 속성을 정의하지 않고 'factory-bean' 속성에 factory메소드를 포함하는 Bean을 정의한다.
      <!-- the factory bean, which contains a method called createInstance() -->
      <bean id="myFactoryBean" class="..."/>
      
      <!-- the bean to be created via the factory bean -->
      <bean id="exampleBean"
        factory-bean="myFactoryBean"
        factory-method="createInstance"/>