작심삼일러의 스프링 시작하기(5)

서은경·2022년 8월 1일
0

Spring

목록 보기
8/43

컨테이너 초기화와 종료

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

public class Main {

    public static void main(String[] args) {
    
    	// 1. 컨테이너 초기화
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppContext.class);
        
        // 2. 컨테이너에서 빈 객체를 구해서 사용
        Greeter g = ctx.getBean("greeter", Greeter.class);
        String msg = g.greet("스프링");
        System.out.println(msg);

        Greeter g1 = ctx.getBean("greeter", Greeter.class);
        Greeter g2 = ctx.getBean("greeter", Greeter.class);
        System.out.println("(g1 == g2) = " + (g1 == g2));
        
        // 3. 컨테이너 종료
        ctx.close();
    }
}

스프링 컨테이너는 설정 클래스에서 정보를 읽어와 알맞은 빈 객체를 생성하고 각 빈을 연결(의존 주입) 하는 작업을 수행한다.
컨테이너 초기화가 완료되면 컨테이너는 사용할 수 있다. 컨테이너를 사용한다는 것은 getBean() 같은 메서드를 통해 컨테이너에 보관된 빈 객체를 구한다는 것을 뜻한다.

  • 컨테이너 초기화 -> 빈 객체의 생성, 의존 주입, 초기화
  • 컨테이너 종료 -> 빈 객체의 소멸

스프링 빈 객체의 라이프 사이클

스프링 컨테이너는 빈 객체의 라이프 사이클을 관리한다.
객체 생성 -> 의존 설정 -> 초기화 -> 소멸

스프링 컨테이너는 빈 객체를 초기화하고 소멸하기 위해 빈 객체의 지정한 메서드를 호출한다.

  • org.springframework.beans.factory.InitializingBean
  • org.springframework.beans.factory.DisposableBean
public interface InitializingBean {
	void afterPropertiesSet() throws Exception;
}

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

빈 객체가 InitializingBean 인터페이스를 구현하면 스프링 컨테이너는 초기화 과정에서 빈 객체의 afterPropertiesSet() 메서드를 실행한다. 빈 객체를 생성한 후 초기화 과정이 필요하면 이 인터페이스를 상속하고 메서드를 알맞게 구현하면 된다.

스프링 컨테이너는 빈 객체가 DisposableBean 인터페이스를 구현한 경우 소멸 과정에서 빈 객체의 destroy() 메서드를 실행한다. 초기화와 같이 소멸 과정이 필요하면 알맞게 쓰면 된다.

두 인터페이스를 사용하고 싶지 않은 경우에는 스프링 설정에서 직접 메서드를 지정할 수도 있다.

	@Bean(initMethod = "connect", destroyMethod = "close")
    public Client2 client2() {
        Client2 client = new Client2();
        client.setHost("host");
        return client;
    }

@Bean 어노테이션의 initMethos, destroyMethod 속성을 이용하면 된다.
다만 ‼️ 초기화 메서드가 두번 불리지 않도록 주의해야 한다.

초기화와 소멸 과정이 필요한 예가 데이터베이스 커넥션 풀이다. 커넥션 풀을 위한 빈 객체는 초기화 과정에서 데이터베이스 연결을 생성한다. 컨테이너를 사용하는 동안 연결을 유지하고 빈 객체를 소멸할 때 사용 중인 데이터베이스 연결을 끊어야 한다.

또 다른 예로는 채팅 클라이언트가 있다. 채팅 클라이언트는 시작할 때 서버와 연결을 생성하고 종료할 때 연결을 끊는다. 이때 서버와의 연결을 생성하고 끊는 작업을 초기화 시점과 소멸 시점에 수행하면 된다.

빈 객체의 생성과 관리 범위

한 식별자에 대해 한 개의 객체만 존재하는 빈은 싱글톤 범위를 갖는다. 별도 설정을 하지 않으면 빈은 싱글통 범위를 갖는다.

사용 빈도가 낮긴 하지만 프로토타입 범위의 빈을 설정할 수도 있다. 빈의 범위를 프로토타입으로 지정하면 빈 객체를 구할 때마다 매번 새로운 객체를 생성한다.

package config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import spring.Client;
import spring.Client2;

@Configuration
public class AppCtxWithPrototype {

    @Bean
    @Scope("prototype")
    public Client client() {
        Client client = new Client();
        client.setHost("host");
        return client;
    }

    @Bean(initMethod = "connect", destroyMethod = "close")
    @Scope("singletone")
    public Client2 client2() {
        Client2 client = new Client2();
        client.setHost("host");
        return client;
    }
}

프로토타입 범위를 갖는 빈은 완전한 라이프사이클을 따르지 않는다는 점에 주의해야 한다. 스프링 컨테이너는 프로토타입의 빈 객체를 생성하고 프로퍼티를 설정하고 초기화작업까지는 수행하지만, 컨테이너를 종료한다고 해서 생성한 프로토타입 빈 객체의 소멸 메서드를 실행하지는 않는다.
따라서 ‼️ 프로토타입 범위의 빈을 사용할 때에는 빈 객체의 소멸 처리를 코드에서 직접 해야한다.

0개의 댓글