ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Spring]bean 객체의 생명주기
    프로그래밍 언어/Spring 2019. 7. 20. 12:51

    오늘 정리 할 내용은 빈 객체의 생명주기와 범위 입니다.

    많이 공부해본 부분이 아니라서 이번에 좀 자세히 봤습니다😊


    1. 스프링 컨테이너의 초기화와 종료

    스프링 컨테이너는 초기화 ~ 종료 까지의 생명주기를 가집니다.


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // 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>

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    package 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>

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    package 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>

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    package 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>

    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"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://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. 객체 범위


    지난 포스팅에서 스프링 컨테이너는 빈 객체를 한 개만 생성한다고 했었습니다.


    1
    2
    Client client1 = (Client)ctx.getBean("client");
    Client client2 = (Client)ctx.getBean("client");



    스프링에선 한 개의 <bean> 태그에 대해 한 개의 빈 객체만을 생성합니다.


    이름을 다르게 해서 객체를 생성한다고 해도 식별자가 같기 때문에 같은 객체입니다.


    이를 싱글톤 범위를 갖는다고 표현합니다.(단일 객체)


    하지만 프로토타입(prototype)을 사용해서 객체를 생성할 때마다 새로운 객체를 생성하게 할 수 있습니다.


    1
    2
    3
    <bean id="client1" class="spring.Client" scope="prototype">
         <property name="host" value="서버"/>
    </bean>        



    프로토타입 설정 방법은 <bean> 태그에 scope="prototype" 만 써주시면 됩니다.


    이렇게 빈 객체를 생성해놓으면 객체를 생성 할 때마다 새로운 객체를 생성하게 됩니다!(쉽죠?ㅎㅎ)


    참고로 <bean> 객체의 scope default는 "singleton" 입니다.



    빈 객체의 생명주기를 처음 공부해봤는데, 스프링의 전체적인 흐름을 공부하는데 좋은 것 같습니다!!

    다음 포스팅은 AOP에 대해 올리려 합니다☺️

Designed by Tistory.