이번 절에서는 빈의 범위(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");
}
'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");
}
'kiaEngine'의 범위는 프로토타입(prototype)으로 설정되었다. 따라서 getBean() 메서드를 호출할 때마다 새로운 빈을 만들어 반환한다. e3와 e4를 비교해 보면 다르다고 출력된다.
참고도서 : https://freelec.co.kr/book/1674/
[열혈강의] 자바 웹 개발 워크북
[열혈강의] 자바 웹 개발 워크북
freelec.co.kr
'교재 실습 > 자바 웹 개발 워크북' 카테고리의 다른 글
146. 날짜 값 주입 (2) (0) | 2022.11.08 |
---|---|
145. 날짜 값 주입 (1) (1) | 2022.11.07 |
143. 팩토리 메서드와 팩토리 빈 (2) (0) | 2022.11.06 |
142. 팩토리 메서드와 팩토리 빈 (1) (0) | 2022.10.31 |
141. 컬렉션 값 주입 (2) (0) | 2022.10.26 |
댓글