1. Servelt 생명주기
클라이언트가 Servlet에 요청을 하면, Servlet은 바로 호출이 되지 않습니다.
Servlet은 객체를 생성하고 초기화 작업을 거친 후, 요청을 처리하는 생명 주기를 갖고 있습니다.
(1) 간략한 과정
-서블릿은 init () 메소드를 호출하여 초기화된다.
-서블릿은 service () 메소드를 호출 하여 클라이언트의 요청을 처리한다.
-서블릿은 destroy () 메소드를 호출하여 종료된다.
-마지막으로, 서블릿은 JVM의 가비지 컬렉터에 의해 가비지 수집된다.
(2) 상세한 과정
JSP 페이지도 결국은 Servlet이기 때문에 아래와 같은 생명 주기를 갖습니다.
- 요청이 오면, Servlet 클래스가 로딩되어 요청에 대한 Servlet 객체가 생성됩니다.
- 서버는 init() 메소드를 호출해서 Servlet을 초기화 합니다.
- service() 메소드를 호출해서 Servlet이 브라우저의 요청을 처리하도록 합니다.
- service() 메소드는 특정 HTTP 요청(GET, POST 등)을 처리하는 메서드 (doGet(), doPost() 등)를 호출합니다.
- 서버는 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 = "소멸에 사용될 메서드"
'Spring' 카테고리의 다른 글
POJO 란? (Spring) (0) | 2021.03.14 |
---|---|
SpringFramework(스프링프레임워크)란? (0) | 2021.03.14 |