Spring Bean Life Cycle (빈 생명주기 관리)
- 프로그래밍/Spring FWK
- 2015. 12. 28. 15:31
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 InitializingBean, DisposableBean{
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("BEAN 생성 및 초기화 : afterPropertiesSet() 호출됨");
}
@Override
public void destroy() throws Exception {
System.out.println("BEAN 생성 소멸 : destroy 호출됨");
}
// 중략...
} |
- InitializingBean Interface를 구현하면 Spring 에서 Bean생성과 properties의존성 주입 후 콜백 afterPropertiesSet()을 호출
- DispoableBean Interface를 구현하면 Spring 에서 Bean소멸 전 콜백 destroy()를 호출
- Bean 정의시 메소드 지정
1
2 |
<bean id="BBean" class="com.spring.bean.BSimpleClass"
init-method="init" destroy-method="destroy"/> |
- xml설정 파일 <bean>에서 init-method 지정 시 Bean생성과 properties의존성 주입 후 지정한 메소드 호출
- 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 호출됨");
}
} |
- @PostConstruct 어노테이션을 지정한 메소드를 Bean생성과 properties의존성 주입 후 콜백으로 호출
- @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 |
수행결과
정보: 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 호출됨
다운로드
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 |
수행결과
정보: 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 |
수행결과
정보: 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 호출됨
다운로드
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 |
이 글을 공유하기