본문 바로가기
공부/Spring

[chap6] 빈 라이프사이클과 범위

by JERO__ 2022. 5. 20.

6장 빈 라이프사이클과 범위

6-1. 컨테이너 초기화와 종료

// 1. 컨테이너 초기화
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppContext.class);

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

// 3. 컨테이너 종료
ctx.close();
  • 컨테이너 초기화 : Bean 객체 생성, 의존 주입, 초기화
  • 컨테이너 종료 : 빈 객체의 소멸

6-2. 스프링 빈 객체의 라이프사이클

  1. Bean 객체 생성
  2. 의존 설정 : 이 때, 의존 자동 주입이 수행됨
  3. 초기화 : Bean 객체 초기화
  4. 소멸 : Bean 객체 소멸

6-2-1. Bean 초기화, 소멸

  • 초기화
public interface InitializingBean{
	void afterPropertiesSet() throws Exception;
}

→ Bean 객체가 InitializingBean를 구현하면 초기화 과정에서 afterPropertiesSet() 메서드를 실행

  • 소멸
public interface DisposableBean{
	void destroy() throws Exception;
}
  • Bean 객체가 DisposableBean를 구현하면 초기화 과정에서 destroy() 메서드를 실행

예시)

  • main
public static void main(String[] args) throws IOException {
		AbstractApplicationContext ctx = 
				new AnnotationConfigApplicationContext(AppCtx.class);
		Client client = ctx.getBean(Client.class);
		client.send();
		ctx.close();
	}
  • AppCtx
@Configuration
public class AppCtx {

	@Bean
	public Client client() {
		Client client = new Client();
		client.setHost("host");
		return client;
	}
}
  • Client
public class Client implements InitializingBean, DisposableBean {

	private String host;

	public void setHost(String host) {
		this.host = host;
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		System.out.println("Client.afterPropertiesSet() 실행");
	}

	public void send() {
		System.out.println("Client.send() to " + host);
	}

	@Override
	public void destroy() throws Exception {
		System.out.println("Client.destroy() 실행");
	}
}
  • 결과
Client.afterPropertiesSet() 실행
Client.send() to host
17:59:47.532 [main] DEBUG org.springframework.context.annotation.AnnotationConfigApplicationContext - Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@10dba097, started on Thu May 19 17:59:47 KST 2022
Client.destroy() 실행

6-2-2. Bean 객체의 초기화와 소멸 : 커스텀 메서드

  • 모든 클래스가 InitializingBean, DisposableBean 을 상속받아 구현할 수 있는것이 아님
    • 외부에서 제공받은 클래스를 스프링 빈 객체로 설정하는 경우 → 직접 메서드를 지정할 수 있다.
  • Client2 추가
public class Client2 {

	private String host;

	public void setHost(String host) {
		this.host = host;
	}

	public void connect() {
		System.out.println("Client2.connect() 실행");
	}

	public void send() {
		System.out.println("Client2.send() to " + host);
	}

	public void close() {
		System.out.println("Client2.close() 실행");
	}
}
  • AppCtx
@Configuration
public class AppCtx {

	@Bean
	public Client client() {
		Client client = new Client();
		client.setHost("host");
		return client;
	}
	
	**@Bean(initMethod = "connect", destroyMethod = "close")  // 직접 지정할 수 있다**
	public Client2 client2() {
		Client2 client = new Client2();
		client.setHost("host");
		return client;
	}
}
  • 실행 결과
Client.afterPropertiesSet() 실행
18:06:36.496 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'client2'
Client2.connect() 실행
Client.send() to host
18:06:36.554 [main] DEBUG org.springframework.context.annotation.AnnotationConfigApplicationContext - Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@10dba097, started on Thu May 19 18:06:36 KST 2022
Client2.close() 실행
Client.destroy() 실행

→ 설정 클래스는 자바 코드이므로, initMethod, destroyMethod 속성을 빈 설정 메서드에서 직접 초기화를 수행해도 된다.

@Bean(initMethod = "connect")
	@Scope("singleton")
	public Client2 client2() {
		Client2 client = new Client2();
		client.setHost("host");
		return client;
	}
  • 주의사항
    • initMethod, destroyMethod 속성에 지정한 메서드는 파라미터가 없어야 한다.
    • 초기화 메서드가 두 번 불리지 않도록 한다.

6-3. Bean 객체의 생성과 관리 범위

1. 싱글톤

Client client1 = ctx.getBean(Client.class);
Client client2 = ctx.getBean(Client.class);
// client1 == client2 -> true

2. 프로토타입

  • 빈 등록 시, @Scope를 prototype 으로 지정한다.
@Bean
@Scope("prototype")
public Client client() {
	Client client = new Client();
	client.setHost("host");
	return client;
}
Client client1 = ctx.getBean(Client.class);
Client client2 = ctx.getBean(Client.class);
// client1 == client2 -> false
  • 매번 새로운 객체를 생성
  • default는 singleton 이다.

2-1. 프로토타입 주의사항

  • 빈의 완전한 라이프사이클을 따르지 않는다.
    • 컨테이너 종료 후 Bean 객체의 소멸 메서드를 실행하지 않는다.
    • Bean 객체의 소멸 처리를 코드에서 직접 해야한다.

'공부 > Spring' 카테고리의 다른 글

[chap8] DB연동  (0) 2022.05.27
[chap7] AOP 프로그래밍  (0) 2022.05.20
[chap5] 컴포넌트 스캔  (0) 2022.05.20
[chap4] 의존 자동 주입  (0) 2022.05.20
[chap3] 스프링 DI  (0) 2022.05.20

댓글