상세 컨텐츠

본문 제목

[스프링2] 6장. 빈 라이프사이클과 범위

22-23/22-23 Spring 2

by YUZ 유즈 2022. 10. 13. 10:02

본문

728x90

이 장의 키워드

# 컨테이너 초기화와 종료

# 빈 객체의 라이프사이클

# 초기화, 소멸 과정 설정

# 싱글톤 범위, 프로토타입 범위


 

# 컨테이너 초기화와 종료

스프링 컨테이너는 초기화와 종료라는 라이프사이클을 갖는다.

아래 코드는 2장에서 작성한 Main.java의 일부다.

// 1. 컨텍스트 객체 생성 및 2. 컨테이너 초기화
AnnotationConfigApplicationContext ctx = 
	new AnnotationConfigApplicationContext(AppContext.class);

// 3. 컨테이너에서 빈 객체를 구해서 사용
Greeter g = ctx.getBean("greeter", Greeter.class);
String msg = g.greet("스프링");
System.out.println(msg);

// 4. 컨테이너 종료
ctx.close();
  1. AnnotationConfigApplicationContext의 생성자를 이용해 컨텍스트 객체를 생성하고
    이 시점에 스프링 컨테이너를 초기화한다.
  2. 스프링 컨테이너 초기화 :
    스프링 컨테이너는 설정 클래스(@Configuration)에서 정보를 읽어와
    알맞은 빈 객체를 생성하고 각 빈을 연결(의존 주입)한다.
  3. 컨테이너 사용 가능 상태: getBean()으로 컨테이너에 보관된 빈 객체를 구할 수 있다.
  4. 컨테이너 종료: 예시에서는 close() 메서드를 사용했다.
    (이 메서드는 AbstractApplicationContext 클래스에 정의되어 있다.)
    * 자바 설정을 사용하는 AnnotationConfigApplicationContext 클래스,
       XML 설정을 사용하는 GenericXmlApplicationContext 클래스 모두
       이 클래스를 상속받고 있어 사용할 수 있다.

 

# 빈 객체의 라이프사이클

스프링 컨테이너는 빈 객체의 라이프사이클을 관리한다.

컨테이너가 관리하는 빈 객체의 라이프사이클은 다음과 같다.

빈 객체의 초기화와 소멸: 스프링 인터페이스

스프링 컨테이너는 빈 객체를 초기화하고 소멸시킬 때, 다음 인터페이스에 정의된 빈 객체 메서드를 호출한다.

초기화 과정이나 소멸 과정에 동작을 추가하고 싶다면, 아래의 인터페이스를 상속하고 메서드를 알맞게 구현하면 된다.

public interface InitializingBean {
	void afterPropertiesSet() throws Exception;
}

public interface DisposableBean {
	void destroy() throws Exception;
}

초기화, 소멸 과정이 필요한 예 1) 데이터베이스 커넥션 풀을 위한 객체

  • 초기화 과정: DB 연결을 생성한다.
  • 컨테이너를 사용하는 동안: 연결을 유지한다.
  • 빈 객체를 소멸할 때: 사용 중인 DB 연결을 끊어야 한다.

초기화, 소멸 과정이 필요한 예 2) 채팅 클라이언트

  • 초기화 과정: 서버와의 연결을 생성한다.
  • 종료 시: 서버와의 연결을 해제한다.

빈 객체의 초기화와 소멸: 커스텀 메서드

Java 언어 특성상 두 개 이상의 인터페이스를 한 번에 상속받을 수 없다.

따라서 위의 인터페이스를 상속할 수 없는 경우가 있는데,

이때 스프링 설정(@Configuration)에서 직접 메서드를 지정하면 된다.

해당 클래스가 갖고 있는 메서드 중에서 초기화 또는 소멸 시 호출할 메서드를 지정할 수 있다.

// 설정 클래스에서
@Bean(initMethod = "초기화 시 호출할 메소드 이름", destroyMethod = "소멸 시 호출할 메소드 이름")

사용 예시)

// 설정 클래스에서
@Bean(initMethod = "connect", destroyMethod = "close")
public Client2 client2() {
	Client2 client = new Client2();
    client.setHost("host");
    return client;
}

// 초기화 메서드를 설정하는 대신 생성자 안에서 초기화를 직접 수행할 수도 있다.
@Bean(destroyMethod = "close")
public Client2 client2() {
	Client2 client = new Client2();
    client.setHost("host");
    client.connect();
    return client;
}

주의점) 빈 설정 코드에서 직접 실행 시 초기화 메서드가 두 번 호출되지 않도록 한다.

아래의 경우 afterPropertiesSet()을 호출했으므로 InitializingBean 인터페이스를 구현한 클래스이다.

이 인터페이스를 구현하면 빈 객체 생성 이후에 afterPropertiesSet() 메소드를 호출하도록 되어 있으므로,

빈 설정 시 한 번, 빈 객체 생성 이후에 한 번으로 총 두 번 호출되는 것이다.

@Bean(destroyMethod = "close")
public Client2 client2() {
	Client2 client = new Client2();
    client.setHost("host");
    client.afterPropertiesSet();  // 주의
    return client;
}

 

 

# 싱글톤 범위, 프로토타입 범위

 

빈은 기본적으로 싱글톤 범위의 객체로, 동일한 이름을 갖는 빈 객체를 구하면 동일한 객체를 반환한다.

자주 쓰이지는 않지만 프로토타입 범위의 빈을 설정할 수도 있다. 이렇게 설정되면 동일한 이름의 빈 객체를 구할 때마다 매번 새로운 객체를 생성하게 된다.

 

사용 예시)

// 설정 클래스에서

@Bean
@Scope("prototype")  // 프로토타입 범위 지정


@Bean
@Scope("singleton")  // 싱글톤 범위 지정(기본값)

주의점) 프로토타입 범위를 갖는 빈은 완전한 라이프사이클을 따르지 않는다.

스프링 컨테이너는 프로토타입의 빈 객체 생성 시 프로퍼티 설정, 초기화 작업까지 수행하지만

컨테이너 종료 시 프로토타입 빈 객체의 소멸 메서드를 실행하지는 않는다.

따라서 소멸 처리를 코드에서 직접 해야 한다.

 

 

 


Quiz.

1. 스프링 컨테이너는 (초기화)와 (종료)라는 라이프사이클을 갖는다.

2. 스프링 컨테이너는 (빈 객체)의 라이프사이클을 관리하며, 이는 (객체 생성, 의존 설정, 초기화, 소멸) 네 단계로 이루어져 있다.

3. 컨테이너가 사용 가능하다는 것은 (getBean()으로 컨테이너에 보관된 빈 객체를 구)할 수 있다는 의미이다.

4. 초기화 메소드를 빈 객체 생성자에서 직접 실행 시 (두 번 호출되지) 않도록 주의해야 한다.

5. 커스텀한 메소드를 사용하고 싶을 때는 스프링 설정 파일에
    @Bean(initMethod= "초기화메소드이름", destroyMethod="소멸메소드이름") 으로 설정한다.

6. 빈은 기본적으로 (싱글톤) 범위의 객체로, 동일한 이름을 갖는 빈 객체를 구하면 (항상 동일한) 객체를 반환한다.

7. (프로토타입) 범위의 빈으로 설정하면 동일한 이름의 빈 객체를 구할 때마다 (매번 새로운) 객체를 반환한다.

8. (프로토타입) 범위를 갖는 빈은 완전한 라이프사이클을 따르지 않는다: (초기화)는 하지만 (소멸)은 하지 않는다.

 

 

 

1. 생성자 안에서 초기화하는 형태로 바꿔보자.

// 설정 클래스
@Bean(initialMethod = "connect", ___________ = "close")
public Client2 client2() {
    Client2 client = new Client2();
    client.setHost("host");
    return client;
}

// 생성자 안에서 초기화하는 형태로 바꿔보기

 


Corner Spring #2

Editor : 유즈

 

728x90

관련글 더보기