본문 바로가기
교재 실습/자바 웹 개발 워크북

144. 빈의 범위 설정

by Jint 2022. 11. 7.

이번 절에서는 빈의 범위(bean scope)를 설정하는 방법을 배운다. 스프링 IoC 컨테이너는 빈을 생성할 때 기본으로 한 개만 생성한다. getBean() 메서드를 호출하면 계속 동일한 객체를 반환한다. 그러나 설정을 통해 이런 빈의 생성 방식을 조정할 수 있다. 다음은 스프링에서 설정 가능한 빈의 범위를 정리한 표이다.

범위 설명
싱글톤(singleton) 오직 하나의 빈만 생성한다(기본 설정).
프로토타입(prototype) getBean() 메서드를 호출할 때마다 빈을 생성한다.
요청(request) HTTP 요청이 발생할 때마다 생성되며, 웹 애플리케이션에서만 이 범위를 설정할 수 있다.
세션(session) HTTP 세션이 생성될 때마다 빈이 생성되며, 웹 애플리케이션에서만 이 범위를 설정할 수 있다.
전역 세션(globalsession) 전역 세션이 준비될 때 빈이 생성된다. 웹 애플리케이션에서만 이 범위를 지정할 수 있으면, 보통 포틀릿 컨텍스트에서 사용한다.

 

1. 싱글톤과 프로토타입

한 개의 인스턴스만 생성하여 사용하는 싱글톤(singleton) 방식과 매번 요청할 때마다 인스턴스를 생성해 주는 프로토타입(prototype) 방식을 확인해 본다.

 

- 실습 패키지 생성

exam 패키지 아래에 test14 패키지를 생성한다. test13 패키지의 모든 파일을 복사해온다.

 

- beans.xml 빈 설정 파일

exam/test14/beans.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"
	xmlns:p="http://www.springframework.org/schema/p"
    xmlns:c="http://www.springframework.org/schema/c"
 	xsi:schemaLocation="http://www.springframework.org/schema/beans
						http://www.springframework.org/schema/beans/spring-beans.xsd">
						
	<bean id="hyundaiEngine" class="exam.test14.Engine" p:maker="Hyundai" p:cc="1997"/>
	
	<bean id="kiaEngine" class="exam.test14.Engine" p:maker="Kia" p:cc="3000" scope="prototype"/>

</beans>

 

<bean id="hyundaiEngine" class="exam.test14.Engine" p:maker="Hyundai" p:cc="1997"/>

앞의 코드에서는 빈의 범위를 설정하지 않았다. 이렇게 범위를 설정하지 않으면 'singleton'이 기본 범위로 지정된다. 빈의 범위를 정확히 명시하고 싶으면 scope="singleton" 속성을 추가한다.

<bean id="kiaEngine" class="exam.test14.Engine" p:maker="Kia" p:cc="3000" scope="prototype"/>

앞의 코드는 scope 속성의 값을 'prototype'으로 설정하였다. 이 경우 빈 컨테이너에게 'kiaEngine'을 요청할 때마다 매번 새 Engine 인스턴스를 만들어 반환할 것이다.

 

- 빈 컨테이너 테스트

자바 객체의 싱글톤 생성 방식과 프로토타입 생성 방식을 테스트해 본다. test13 패키지에서 복사해 온 테스트 클래스 exam.test14.Test 클래스를 다음과 같이 편집한다.

package exam.test14;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {
	
	public static void main(String[] args) {
		//IoC 컨테이너 준비하여 빈 생성
		ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("exam/test14/beans.xml");
		
		System.out.println("[singleton 방식(기본)]-------------------------");
		
		Engine e1 = (Engine)ctx.getBean("hyundaiEngine");
		Engine e2 = (Engine)ctx.getBean("hyundaiEngine");
		
		System.out.println("e1-->" + e1.toString());
		System.out.println("e2-->" + e2.toString());
		if(e1 == e2) {
			System.out.println("e1 == e2");
		}
		
		System.out.println("[prototype 방식]-------------------------");
		
		Engine e3 = (Engine)ctx.getBean("kiaEngine");
		Engine e4 = (Engine)ctx.getBean("kiaEngine");
		
		System.out.println("e3-->" + e3.toString());
		System.out.println("e4-->" + e4.toString());
		if(e3 != e4) {
			System.out.println("e3 != e4");
		}
	}
	
}

 

Engine e1 = (Engine)ctx.getBean("hyundaiEngine");
Engine e2 = (Engine)ctx.getBean("hyundaiEngine");

System.out.println("e1-->" + e1.toString());
System.out.println("e2-->" + e2.toString());
if(e1 == e2) {
    System.out.println("e1 == e2");
}

그림 1 (exam.test14.Test 클래스 실행 결과)

'hyundaiEngine'은 기본 범위(singleton)로 설정된 객체이다. 따라서 한 개의 인스턴스만 생성된다. getBean() 메서드를 호출하면 매번 같은 객체를 반환한다. 실행 결과를 보면 e1과 e2는 같다고 나온다.

Engine e3 = (Engine)ctx.getBean("kiaEngine");
Engine e4 = (Engine)ctx.getBean("kiaEngine");

System.out.println("e3-->" + e3.toString());
System.out.println("e4-->" + e4.toString());
if(e3 != e4) {
    System.out.println("e3 != e4");
}

그림 2 (exam.test14.Test 클래스 실행 결과)

'kiaEngine'의 범위는 프로토타입(prototype)으로 설정되었다. 따라서 getBean() 메서드를 호출할 때마다 새로운 빈을 만들어 반환한다. e3와 e4를 비교해 보면 다르다고 출력된다.

 

참고도서 : https://freelec.co.kr/book/1674/

 

[열혈강의] 자바 웹 개발 워크북

[열혈강의] 자바 웹 개발 워크북

freelec.co.kr

댓글