Spring Bean Life Cycle (빈 생명주기 관리)

 

Spring Bean Life Cycle (빈 생명주기 관리)

 

 

 

 

스프링을 비롯해 많은 IoC 컨터이너는 자신이 관리하는 Bean의 라이프 사이클을 관리하여 주고 특정 시점에 Bean에게 이를 알려줄 수 있는 메커니즘을 제공한다. 스프링에서는 init 이벤트와 destroy 이벤트가 주로 사용된다. 이 시점에서 이벤트를 캐치하는 방법은 세 가지가 제공된다. 인터페이스 기반,  Bean설정에 의한 Method 기반, JSR-250어노테이션 기반 메커니즘 세가지 방법이다.


Spring Bean Life Cycle 관리방법

아래와 같이 3가지 방법을 제공하며 어플리케이션 설계와 프로젝트 특성에 맞게 원하는 방법을 결정하여 구현하면 된다.

  • 인터페이스 구현

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class SimpleClass implements InitializingBeanDisposableBean{
 
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("BEAN 생성 및 초기화 : afterPropertiesSet() 호출됨");
    }
 
    @Override
    public void destroy() throws Exception {
        System.out.println("BEAN 생성 소멸 : destroy 호출됨");
    }
 
    // 중략...
}

cs

    1. InitializingBean Interface를 구현하면 Spring 에서 Bean생성과 properties의존성 주입 후 콜백 afterPropertiesSet()을 호출
    2. DispoableBean Interface를 구현하면 Spring 에서 Bean소멸 전 콜백 destroy()를 호출

 

    • Bean 정의시 메소드 지정
    1
    2
    <bean id="BBean" class="com.spring.bean.BSimpleClass"
                          init-method="init" destroy-method="destroy"/>

    cs

        1. xml설정 파일 <bean>에서 init-method 지정 시 Bean생성과 properties의존성 주입 후 지정한 메소드 호출
        2. xml설정 파일 <bean>에서 destroy-method 지정 시 Bean소멸 전 콜백으로 지정한 메소드 호출

       

      • JSR-250 어노테이션 지정

      <context:annotation-config/> xml설정 파일에 추가 필요

       

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      public class BSimpleClass {
          
          @PostConstruct
          public void init(){
              System.out.println("BEAN 생성 및 초기화 : init() 호출됨");
          }
       
          @PreDestroy
          public void destroy(){
              System.out.println("BEAN 생성 소멸 : destroy 호출됨");
          }
      }

      cs

        1. @PostConstruct 어노테이션을 지정한 메소드를 Bean생성과 properties의존성 주입 후 콜백으로 호출
        2. @PreDestroy 어노테이션을 지정한 메소드를 Bean 소멸 전 콜백으로 호출

       

      주의사항

      • socope가 prototype의 경우 destroy 이벤트 처리가 불가능.
      • 인터페이스 구현과 Bean정의시 메소드 지정하는 방법은 스프링에 종속적이다. (추후 다른 IoC컨테이너로 이식불가)
      • JSR-250 어노테이션은 스프링에 종속적인 어노테이션이 아닌 JSCP에서 정한 표준으로 추후 다른 IoC 컨테이너로 이식이 가능하다.

       

       

      사용시점

       

      init-method는 주로 의존성이 제대로 주입되었는지 검사(내부 property가 맞게 주입되었는지)하는 경우 사용된다. 만약 init-method가 아니라 의존성 주입에 대한 검사로직을 생성자에서 하는 경우 문제가 발생한다. 왜냐하면 생성하는 시점에는 property주입을 수행하지 않기 때문이다. 대신 init-method는 spring에서 모든 의존성 주입을 완료한 이후에 호출하기 때문에 init-method에서 의존성 주입 유효성 검사를 체크하여야 한다.

       

      destroy는 주로 자원의 반납을 하는 경우 사용된다. 만약 File 처리와 관련된 Class가 존재하고 필요 기능을 전부 사용한 후에 close를 수행하고자 할 때 가장 적절한 위치는 bean이 소멸되기 직전인 destory다. 흔희 io관련된 자원을 close 하는 부분을 destroy에 작성하곤 한다. 별도로 bean 소멸 시 수행할 작업이 있는 경우에 추가 코드를 작성하면 된다.

       



       


      Example (using interface)

       [SimpleClass.java]

      • InitializingBean 인터페이스 구현하여 afterPropertiesSet() 메소드 override
      • DisposableBean 인터페이스 구현하여 destroy() 메소드 override
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      package com.spring.bean;
       
      import org.springframework.beans.factory.DisposableBean;
      import org.springframework.beans.factory.InitializingBean;
       
      public class SimpleClass implements InitializingBean, DisposableBean{
          @Override
          public void afterPropertiesSet() throws Exception {
              System.out.println("BEAN 생성 및 초기화 : afterPropertiesSet() 호출됨");
          }
       
          @Override
          public void destroy() throws Exception {
              System.out.println("BEAN 생성 소멸 : destroy 호출됨");
          }
      }
      cs

       

      [application-context.xml]

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      <?xml version="1.0" encoding="UTF-8"?>
      <beans xmlns="http://www.springframework.org/schema/beans"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns:c="http://www.springframework.org/schema/c"    xmlns:context="http://www.springframework.org/schema/context"
             xmlns:p="http://www.springframework.org/schema/p"    xmlns:util="http://www.springframework.org/schema/util"
             xsi:schemaLocation="http://www.springframework.org/schema/beans    http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 
             http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
                 http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd">
                  
          <!-- 일반적인 Bean 만 정의한다 -->
          <bean id="simpleBean" class="com.spring.bean.SimpleClass"/>
          
      </beans>
      cs

       

      수행결과

      12월 28, 2015 3:59:54 오후 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
      정보: Loading XML bean definitions from class path resource [META-INF/spring/app-context.xml]
      12월 28, 2015 3:59:54 오후 org.springframework.context.support.AbstractApplicationContext prepareRefresh
      정보: Refreshing org.springframework.context.support.GenericXmlApplicationContext@1c794cc: startup date [Mon Dec 28 15:59:54 KST 2015]; root of context hierarchy
      12월 28, 2015 3:59:54 오후 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
      정보: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@1e9315f: defining beans [simpleBean]; root of factory hierarchy
      BEAN 생성 및 초기화 : afterPropertiesSet() 호출됨
      12월 28, 2015 3:59:54 오후 org.springframework.context.support.AbstractApplicationContext doClose
      정보: Closing org.springframework.context.support.GenericXmlApplicationContext@1c794cc: startup date [Mon Dec 28 15:59:54 KST 2015]; root of context hierarchy
      12월 28, 2015 3:59:54 오후 org.springframework.beans.factory.support.DefaultSingletonBeanRegistry destroySingletons
      정보: Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@1e9315f: defining beans [simpleBean]; root of factory hierarchy
      BEAN 생성 소멸 : destroy 호출됨

       


      다운로드

      SpringLifeCycleInterface.zip

       

       


      Example (using xml bean definition)

       [SimpleClass.java]

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      package com.spring.bean;
       
      public class SimpleClass{
       
          public void init() throws Exception {
              System.out.println("BEAN 생성 및 초기화 : afterPropertiesSet() 호출됨");
          }
          
       
          public void exit() throws Exception {
              System.out.println("BEAN 생성 소멸 : destroy 호출됨");
          }
      }
       
      cs

       

      [application-context.xml]

      • bean정의시 init-method="init" 지정
      • bean정의시 destroy-method="destroy" 지정
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      <?xml version="1.0" encoding="UTF-8"?>
      <beans xmlns="http://www.springframework.org/schema/beans"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns:c="http://www.springframework.org/schema/c"    xmlns:context="http://www.springframework.org/schema/context"
             xmlns:p="http://www.springframework.org/schema/p"    xmlns:util="http://www.springframework.org/schema/util"
             xsi:schemaLocation="http://www.springframework.org/schema/beans    http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 
              http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
              http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd">
                  
          <!-- init-method와 destroy-method 지정 -->
          <bean id="simpleBean" class="com.spring.bean.SimpleClass"
                               init-method="init" destroy-method="exit"/>
          
      </beans>
      cs

       

      수행결과

      12월 28, 2015 4:12:36 오후 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
      정보: Loading XML bean definitions from class path resource [META-INF/spring/app-context.xml]
      12월 28, 2015 4:12:36 오후 org.springframework.context.support.AbstractApplicationContext prepareRefresh
      정보: Refreshing org.springframework.context.support.GenericXmlApplicationContext@adf5be: startup date [Mon Dec 28 16:12:36 KST 2015]; root of context hierarchy
      12월 28, 2015 4:12:36 오후 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
      정보: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@8ff9a7: defining beans [simpleBean]; root of factory hierarchy
      BEAN 생성 및 초기화 : init() 호출됨
      12월 28, 2015 4:12:36 오후 org.springframework.context.support.AbstractApplicationContext doClose
      정보: Closing org.springframework.context.support.GenericXmlApplicationContext@adf5be: startup date [Mon Dec 28 16:12:36 KST 2015]; root of context hierarchy
      12월 28, 2015 4:12:36 오후 org.springframework.beans.factory.support.DefaultSingletonBeanRegistry destroySingletons
      정보: Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@8ff9a7: defining beans [simpleBean]; root of factory hierarchy
      BEAN 소멸 : destroy 호출됨

       

      다운로드

      SpringLifeCycleBeanDefinition.zip

       

       


      Example (using JSR-250 annotation)

       [SimpleClass.java]

      • @PostConstruct 메소드 지정
      • @PreDestroy 메소드 지정
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      package com.spring.bean;
       
      import javax.annotation.PostConstruct;
      import javax.annotation.PreDestroy;
       
      public class SimpleClass{
       
          @PostConstruct
          public void init() throws Exception {
              System.out.println("BEAN 생성 및 초기화 : init() 호출됨");
          }
          
          @PreDestroy
          public void exit() throws Exception {
              System.out.println("BEAN 소멸 : destroy 호출됨");
          }
      }
       
      cs

       

       

      [application-context.xml]

      • <context:annotation-config/> 추가
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      <?xml version="1.0" encoding="UTF-8"?>
      <beans xmlns="http://www.springframework.org/schema/beans"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns:c="http://www.springframework.org/schema/c"    xmlns:context="http://www.springframework.org/schema/context"
             xmlns:p="http://www.springframework.org/schema/p"    xmlns:util="http://www.springframework.org/schema/util"
             xsi:schemaLocation="http://www.springframework.org/schema/beans    http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 
              http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
              http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd">
                  
          <context:annotation-config/>
          
          <bean id="simpleBean" class="com.spring.bean.SimpleClass"/>
          
      </beans>
       
      cs

       

      수행결과

      12월 28, 2015 4:17:58 오후 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
      정보: Loading XML bean definitions from class path resource [META-INF/spring/app-context.xml]
      12월 28, 2015 4:17:58 오후 org.springframework.context.support.AbstractApplicationContext prepareRefresh
      정보: Refreshing org.springframework.context.support.GenericXmlApplicationContext@1f9e31e: startup date [Mon Dec 28 16:17:58 KST 2015]; root of context hierarchy
      12월 28, 2015 4:17:58 오후 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
      정보: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@d2e636: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,simpleBean,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor]; root of factory hierarchy
      BEAN 생성 및 초기화 : init() 호출됨
      12월 28, 2015 4:17:58 오후 org.springframework.context.support.AbstractApplicationContext doClose
      정보: Closing org.springframework.context.support.GenericXmlApplicationContext@1f9e31e: startup date [Mon Dec 28 16:17:58 KST 2015]; root of context hierarchy
      12월 28, 2015 4:17:58 오후 org.springframework.beans.factory.support.DefaultSingletonBeanRegistry destroySingletons
      정보: Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@d2e636: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,simpleBean,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor]; root of factory hierarchy
      BEAN 소멸 : destroy 호출됨

       

      다운로드

      SpringLifeCycleAnnotation.zip

       

       


       

      Example (참고사항 : destroy() 동작)

      보통 Spring Application에서는 destroy() 동작시키지 못하고 어플리케이션이 종료 되어버리는 경우가 있다. 이런 경우 applciatonContext 객체에 명시적으로 close()나 destroy()를 호출시켜 주는 방법과 shutdownhook를 등록하여 주는 방법으로 해결 가능하다.

       

      1. applicationContext.close() / .destroy(); 호출

      명시적으로 소멸시점을 사용자가 지정하여 어플리케이션 컨텍스트를 종료 할 수 있다. 단, 어플리케이션의 종료시점을 명확히 알 수 없는 단독 실행형 어플리케이션이나, 비정상 종료 시점에 적절한 destroy() 과정을 거치지 못할 수 있다.

       

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      package com.spring;
       
      import org.springframework.context.support.GenericXmlApplicationContext;
       
      import com.spring.bean.SimpleClass;
       
      public class MainApplication {
       
          public static void main(String[] args) {
              // ApplicationContext 부트스트랩
              GenericXmlApplicationContext appCtx = new GenericXmlApplicationContext();
              appCtx.load("classpath:META-INF/spring/app-context.xml");
              //appCtx.registerShutdownHook();
              appCtx.refresh();
              
              SimpleClass bean = appCtx.getBean("simpleBean", SimpleClass.class);
              
              //appCtx.destroy();
              appCtx.close();
          }
      }
      cs

       

       

      2. applicationContext.registerShutdownHook(); 호출

      권장되는 방법으로 어플리케이션이 어떤 방법으로 종료되어도 자동으로 destroy()를 수행하여 준다. 임의로 destory시점을 정할 수 는 없지만 jvm에 올라가 있는 어플리케이션이 종료되기 전 시점에 자동으로 destroy()를 수행시켜 준다.

       

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      package com.spring;
       
      import org.springframework.context.support.GenericXmlApplicationContext;
       
      import com.spring.bean.SimpleClass;
       
      public class MainApplication {
       
          public static void main(String[] args) {
              // ApplicationContext 부트스트랩
              GenericXmlApplicationContext appCtx = new GenericXmlApplicationContext();
              appCtx.load("classpath:META-INF/spring/app-context.xml");
              appCtx.registerShutdownHook();
              appCtx.refresh();
              
              SimpleClass bean = appCtx.getBean("simpleBean", SimpleClass.class);
       
          }
      }
      cs

       

       

       


      '프로그래밍 > Spring FWK' 카테고리의 다른 글

      Spring facoty-bean, factory-method  (0) 2015.12.30
      Spring FactoryBean Interface  (0) 2015.12.29
      Spring ApplicationContextAware Interface  (0) 2015.12.28
      Spring BeanNameAware Interface  (1) 2015.12.28
      Spring bean 상속  (0) 2015.12.27
      Spring Bean Scope 정리  (0) 2015.12.27
      Spring Method Replace (replaced-method)  (0) 2015.12.18
      Spring Method LookUp Injection  (0) 2015.12.16

      이 글을 공유하기

      댓글

      Email by JB FACTORY