Programming/Spring framework

빈 라이프사이클과 범위,[최범균 스프링5] 2021-06-03

최동훈1 2021. 6. 3. 16:17

우선 자바 빈은 AnnotationConfigApplicatonContext 클래스로 대표되는 스프링 컨테이너에 등록되고, 사라지는데 특정한 주기를 갖는다.

쉽게 설명하자면,

객체생성->의존설정->초기화->소멸 인데, 각 단계별로 설명하자면,

 

1. 객체생성: AnnotationConfigApplicationContext 의 생성자로, 자바 설정클래스가 들어갔을때, 설정클래스에 구현된 자바빈 들의 객체를 생성하고 컨테이너에 등록한다.

2.객체를 생성해서 컨테이너에 등록하는 과정에서 만약 @Autowired에 의한 자동의존 주입이 필요하다면, 기존에 등록된 자바빈 객체들중 해당 타입과 같은 빈을 주입한다.

 

여기까지는 앞서 포스트에서 설명했고, 우리도 다 알고 있는 내용이다. 그러나 다음 두 내용은 새로운 내요이다.

 

3.모든 의존설정이 완료되면, 빈 객체의 초기화를 수행한다. 빈객체를 초기화하기 위해 스프링은 빈 객체의 지정된 메서드를 호출하는데, 커스텀으로 사용자가 직접 @Bean의 값으로 정해주거나, 애초에 등록하려는 클래스에 표준 인터페이스를 상속시켜서, 구해주는 방법이 있다.

 

*여기서 지정된 메서드란, InitializingBean 인터페이스에 구현된 추상메서드인 afterPropertiesSet().-> 초기화 메서드

DisposableBean 인터페이스에 구현된 추상메서드인 destroy()->소멸 메서드이다.

책에서는 우리가 자바빈을 등록하는 클래스가 이 두 인터페이스를 상속받아 구현하면, 스프링이 알아서 빈 사이클 주기를 돌때, 초기화 할때는 afterProperitiesSet()을 호출하고, 소멸시킬때는 destroy() 메서드를 호출시켜 준다고 한다.

 

이전까지 내가 한 실습에서 난 한번도 설정클래스 @Configuration이나(수동설정), 자동 자바빈 등록을 위한 @Component가 붙은 클래스에서 위 두 인터페이스를 구현 한 적이 없다. 그래서 나는 초기화나  소멸의 단계를 눈으로 확인해 보지도 못했고, 생소하게 느낀거 같다.

 

표준 인터페이스를 구현받아서, 빈 초기화, 소멸 주기를 진행할수 있는 코드.

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() 실행");
	}

}

 

 

이 클래스를 @Configuration에 등록 한 뒤, Main 클래스를 실행 하면, afterPropertiesSet(), destroy() 함수를 별도로 호출하지 않았는데도, 빈 라이프사이클 주기에 맞추어

콘솔창에

"Client.afterPropertiesSet() 실행",  "Client.destroy() 실행" 등이 나타남을 볼 수 있다.

아래의 코드는 커스텀 메서드로 사용자가 직접 어떤 메서드를 초기화 시 실행할껀지, 소멸 단계에서 실행할껀지 정할 수 있다.

@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;
	}
}

 그리고 또 난 옛 포스트에서 한번, 자바 빈을 생성해서 컨테이너에 등록할때는 만일 "빈 의 식별자가 동일하다면 한개의 객체만을 생성해서 컨테이너에 등록한다." 라고 했다. 즉, 싱글톤 객체인 것이다.

하지만 여기서 @Scope("prototype") 이런 애너테이션을 붙이면,  싱글톤이 아니라 빈 객체를 getBean 메서드를 통해서 구할 때마다, 매번 새로운 객체를 생성한다.

@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("singleton")
	public Client2 client2() {
		Client2 client = new Client2();
		client.setHost("host");
		return client;
	}
}

 

page 150 공부 완료.

 

 공부시간: 3시간, 순공부/ 프로그래밍 시간:1시간.

 

Input 이 없으면 Output이 절대 없다. 시간을 쏟아붇자.