본문 바로가기

Spring

자바 생명주기(Life Cycle)에 대해 알아보자. (Servlet, Bean)

728x90

1. Servelt 생명주기

 

클라이언트가 Servlet에 요청을 하면, Servlet은 바로 호출이 되지 않습니다.

Servlet은 객체를 생성하고 초기화 작업을 거친 후, 요청을 처리하는 생명 주기를 갖고 있습니다.

 

 

(1) 간략한 과정

 

-서블릿은 init () 메소드를 호출하여 초기화된다.

-서블릿은 service () 메소드를 호출 하여 클라이언트의 요청을 처리한다.

-서블릿은 destroy () 메소드를 호출하여 종료된다.

-마지막으로, 서블릿은 JVM의 가비지 컬렉터에 의해 가비지 수집된다.

 

(2) 상세한 과정

 

JSP 페이지도 결국은 Servlet이기 때문에 아래와 같은 생명 주기를 갖습니다.

  1. 요청이 오면, Servlet 클래스가 로딩되어 요청에 대한 Servlet 객체가 생성됩니다.
  2. 서버는 init() 메소드를 호출해서 Servlet을  초기화 합니다.
  3. service() 메소드를 호출해서 Servlet이 브라우저의 요청을 처리하도록 합니다.
  4. service() 메소드는 특정 HTTP 요청(GET, POST 등)을 처리하는 메서드 (doGet(), doPost() 등)를 호출합니다.
  5. 서버는 destroy() 메소드를 호출하여 Servlet을 제거합니다.

톰캣은 Servlet을 다음과 같이 관리하고 있습니다.

  • Servlet 객체를 생성하고 초기화하는 작업은 비용이 많은 작업이므로, 다음에 또 요청이 올 때를 대비하여 이미 생성된 Servlet 객체는 메모리에 남겨둡니다.
  • 또 톰캣이 종료되기 전이나 reload 전에 모든 Servlet을 제거하게 됩니다.
  • 이렇게 톰캣은 자원을 아끼면서 Servlet을 사용하고 있습니다.

개발자인 우리들도 자원을 효과적으로 사용하기 위해서 노력을 기울여야 합니다.

이에 대한 방법으로 초기화하는데 호출되는 init() 메서드를 활용합니다.

즉, 요청이 매 번 똑같은 로직을 거쳐서 똑같은 결과를 산출하는 작업은 딱 한 번만 수행 되도록 init() 에서 처리하는 것입니다.

예를 들면, doGet()에서 헤더를 추가하는 request.setCharacterEncoding("utf-8"); 메서드 같은 것들이 있습니다.

 


2. Bean 생명주기

 

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

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

 

// 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>

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>

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>

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>

<?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 = "소멸에 사용될 메서드" 

728x90

'Spring' 카테고리의 다른 글

POJO 란? (Spring)  (0) 2021.03.14
SpringFramework(스프링프레임워크)란?  (0) 2021.03.14