-
[Spring]bean 객체의 생명주기프로그래밍 언어/Spring 2019. 7. 20. 12:51
오늘 정리 할 내용은 빈 객체의 생명주기와 범위 입니다.
많이 공부해본 부분이 아니라서 이번에 좀 자세히 봤습니다😊
1. 스프링 컨테이너의 초기화와 종료
스프링 컨테이너는 초기화 ~ 종료 까지의 생명주기를 가집니다.
12345678910// 1. 컨테이너 초기화ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");// 2. 컨테이너 사용Greeter g = (Greeter)ctx.getBean("greeter");String msg = g.greet("안녕하세요");System.out.println(msg);// 3. 컨테이너 종료((ConfigurabeApplicationContext)ctx).close();아주 기본적인 스프링 컨테이너의 생명주기 입니다.
1. ApplicationContext를 이용해서 객체를 생성하고 스프링 컨테이너를 초기화 합니다.
2. getBean()과 같은 메서드를 이용해서 컨테이너에 있는 빈 객체를 사용합니다.
3. close() 메서드를 이용해서 컨테이너를 종료합니다.
※ 스프링 컨테이너 초기화 / 종료 시 수행되는 작업
▶ 컨테이너 초기화 : 빈 객체 생성, 초기화 및 의존 객체 주입
▶ 컨테이너 종료 : 빈 객체 소멸
2. 빈 객체의 생명주기
1) 스프링 컨테이너를 초기화 할 때, 가장 먼저 빈 객체를 생성합니다.
2) 빈 객체 생성 후, <property> 태그로 지정한 의존을 설정합니다. (의존 주입도 이 단계에서 수행됩니다!)
3) 모든 의존 설정이 완료되면, 빈 객체 초기화를 합니다.
(빈 객체를 초기화하기 위해 빈 객체의 지정한 메서드를 호출!!)
4) 스프링 컨테이너를 종료하면, 스프링 컨테이너는 빈 객체를 소멸 시킵니다.
(빈 객체의 소멸을 처리하기 위해 빈 객체의 지정한 메서드를 호출!!)
2-1. 빈 객체의 초기화와 소멸(스프링 인터페이스)
빈 객체를 초기화하고 소멸하기 위해서는 지정한 메서드가 필요하다고 했는데,
아래 코드에 해당 메서드가 선언되어 있습니다.
두 개의 메서드는 InitializingBean, DisposableBean 라는 인터페이스가 정의되어 있는,
afterPropertiesSet(), destroy() 입니다.
<Client.Java>
12345678910111213141516171819202122232425262728package spring;import org.springframework.beans.factory.DisposableBean;import org.springframework.beans.factory.InitializingBean;public class Client implements InitializingBean, DisposableBean {private String host;public void setHost(String host) {this.host = host;System.out.println("Client.setHost() 실행");}// 빈 객체 생성 후 초기화 과정이 필요할 때 구현public void afterPropertiesSet() throws Exception {System.out.println("Client.afterPropertiesSet() 실행");}public void send() {System.out.println("Client.send() to" + host);}// 빈 객체의 소멸 과정이 필요한 경우 구현public void destroy() throws Exception {System.out.println("Client.destroy() 실행");}}빈 객체가 InitializingBean 인터페이스를 상속받았다면, 스프링 컨테이너에서 빈 객체 생성 후,
초기화 과정이 필요한 경우 InitializingBean에 정의되어 있는 afterPropertiesSet() 메서드를 사용하면 됩니다.
반대로 빈 객체를 소멸해야 할 때는 DisposableBean 인터페이스를 상속받고,
destory() 메서드를 이용해서 빈 객체 소멸을 구현해주면 됩니다 ^^
이런 초기화 / 소멸 과정이 필요한 가장 좋은 예는 데이터베이스 커넥션 풀입니다.
커넥션 풀을 위한 객체가 초기화 과정에서 데이터베이스와 연결을 생성하고 컨테이너를 사용하는 동안 연결을 유지시켜주고,
빈 객체를 소멸할 때 사용 중인 데이터베이스 연결을 끊어주는 방식입니다.
(이런 예가 있다는 것만 알아두셔도 됩니다☺️ 저도 잘 몰랐어요;;)
위의 코드는 스프링 인터페이스를 이용한 초기화 / 소멸 메서드가 실행되는 걸 확인하는 예제입니다.
아래 코드는 메인 코드입니다. Client.Java 와 Main.Java를 보고 실행결과를 생각해 보세요!
<Main.Java>
1234567891011121314151617181920package main;import org.springframework.context.ApplicationContext;import org.springframework.context.ConfigurableApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import spring.Client;public class Main {public static void main(String[] args) {ApplicationContext bean = new ClassPathXmlApplicationContext("springconf.xml");Client c = (Client)bean.getBean("client");c.send();((ConfigurableApplicationContext)bean).close();}}실행 결과는 다음과 같습니다.
즉, 스프링 컨테이너는 빈 객체의 프로퍼티 설정을 하고 완료하고 초기화 메서드를 실행한다는 걸 알 수 있습니다.
destory() 메서드는 스프링 컨테이너를 종료하면 호출되는 것도 알 수 있습니다.
만약 close() 메서드로 컨테이너를 종료하지 않는다면 빈 객체도 소멸되지 않고, destory() 메서드도 실행되지 않습니다!
<실행 결과>
만약, 인터페이스를 사용하지 않고 빈 객체의 초기화와 소멸을 구현하려면 스프링 설정에서 직접 메서드를 지정해주면 됩니다.(.xml)
<Client2.Java>
123456789101112131415161718192021222324package spring;public class Client2 {private String host;public void setHost(String host) {this.host = host;System.out.println("client2.setHost 실행");}public void connect() throws Exception{System.out.println("client2.connect() 실행");}public void send() {System.out.println("client2.send() to " + host);}public void close() throws Exception{System.out.println("client2.close() 실행");}}<springconf.xml>
12345678910111213<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="client2" class="spring.Client2"init-method="connect" destroy-method="close"><property name="host" value="서버2"/></bean></beans>bean 객체를 생성할 때 바로 메서드를 넣어주는 방법입니다.
init-method = "초기화에 사용될 메서드" , destroy-method = "소멸에 사용될 메서드"
3. 객체 범위
지난 포스팅에서 스프링 컨테이너는 빈 객체를 한 개만 생성한다고 했었습니다.
12Client client1 = (Client)ctx.getBean("client");Client client2 = (Client)ctx.getBean("client");스프링에선 한 개의 <bean> 태그에 대해 한 개의 빈 객체만을 생성합니다.
이름을 다르게 해서 객체를 생성한다고 해도 식별자가 같기 때문에 같은 객체입니다.
이를 싱글톤 범위를 갖는다고 표현합니다.(단일 객체)
하지만 프로토타입(prototype)을 사용해서 객체를 생성할 때마다 새로운 객체를 생성하게 할 수 있습니다.
123<bean id="client1" class="spring.Client" scope="prototype"><property name="host" value="서버"/></bean>프로토타입 설정 방법은 <bean> 태그에 scope="prototype" 만 써주시면 됩니다.
이렇게 빈 객체를 생성해놓으면 객체를 생성 할 때마다 새로운 객체를 생성하게 됩니다!(쉽죠?ㅎㅎ)
참고로 <bean> 객체의 scope default는 "singleton" 입니다.
빈 객체의 생명주기를 처음 공부해봤는데, 스프링의 전체적인 흐름을 공부하는데 좋은 것 같습니다!!
다음 포스팅은 AOP에 대해 올리려 합니다☺️
'프로그래밍 언어 > Spring' 카테고리의 다른 글
[Spring]스프링 MVC 기초(구조) (0) 2019.08.01 [Spring] 스프링 DB 연동 (0) 2019.07.20 [Spring]AOP 정의 및 용어 정리 (0) 2019.07.20 [Spring]스프링 프로젝트 생성 및 DI(의존 주입) (0) 2019.07.17