본문 바로가기

Spring

[Spring] Bean의 범위

[해당 포스트는 개인적으로 공부를 하고 차후에 참고용으로 하고자 작성한 것입니다.
따라서 잘못된 부분이나 부족한 부분이 있을 수 있기에 참고하시기 바랍니다.]

Bean의 범위는 크게 2가지로 나뉜다.

  1. Singleton : 동일한 Bean 객체는 동일한 타입에 대해서는 기본적으로 한 개만 생성된다.
  2. Prototype : Singleton과 반대되는 Type으로 동일한 Bean 객체를 사용하더라도 여러 번 호출하면 객체가 여러 개 생성된다.

Singleton

Spring Container에서 생성된 Bean 객체의 경우 동일한 타입에 대해서는 기본적으로 한 개만 생성이 되며, getBean() 메소드를 호출될 때 동일한 객체가 반환된다.

 

다음의 예제는 동일한 Bean을 이용하여 인스턴스를 2개 생성한 후, 서로의 주소가 같은지 비교하는 예제이다.

 

application-context.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"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
 		http://www.springframework.org/schema/beans/spring-beans.xsd">
	
	<bean id="injectionBean" class="scope.ex.InjectionBean"/>
	<bean id="dependencyBean" class="scope.ex.DependencyBean">
		<constructor-arg ref="injectionBean"></constructor-arg>
		<property name="injectionBean" ref="injectionBean"/>
	</bean>
</beans>

 

injextionBean과 dependencyBean을 생성하고, dependencyBean의 생성자에는 injectionBean을 주입시킨다.

또한 injectionBean이라는 이름의 변수로 사용하는 값들을 injectionBean을 주입한다.

 

InjectionBean.java

package scope.ex;

public class InjectionBean {

}

 

단순한 껍데기 Class를 생성한다.

 

DependencyBean.java

package scope.ex;

public class DependencyBean {
	
	private InjectionBean injectionBean;
	
	public DependencyBean(InjectionBean injectionBean) {
		System.out.println("Dependency Bean Constructor.");
		this.injectionBean = injectionBean;
	}
	
	public void setInjectionBean(InjectionBean injectionBean) {
		System.out.println("Dependency Bean Setter.");
		this.injectionBean = injectionBean;
	}
}

 

InjectionBean 객체를 주입할 수 있는 방법 2가지가 제공된다. 생성자를 통해서 주입하거나 setInjectionBean을 호출하여 주입할 수 있다. 그러나 이미 application-context.xml에서 처리하였기에 별도로 호출할 필요가 없이 주입되어 있다.

 

Main.java

package scope.ex;

import org.springframework.context.support.GenericXmlApplicationContext;

public class MainClass {

	public static void main(String[] args) {
		
		/* GenericXmlApplicationContext 객체를 통해 application-context.xml 파일을 읽어온다.
		 Spring Container가 생성된다. */
		GenericXmlApplicationContext container = new GenericXmlApplicationContext(
				"applicationContext.xml");
		
		/* Spring Container에서 생성된 Bean을 가져온다.
		  두개 모두 dependencyBean의 Bean을 가져온다. */
		DependencyBean dependency1 = container.getBean("dependencyBean", DependencyBean.class);
		DependencyBean dependency2 = container.getBean("dependencyBean", DependencyBean.class);
		
		/* 두 Bean이 참조하는 값이 같은지 확인한다. */
		if (dependency1.equals(dependency2)) {
			System.out.println("dependency is equal.");
		} else {
			System.out.println("dependency is not equal.");
		}
		
		container.close();
	}	
}

 

결과 화면

 

dependency1과 dependency2의 인스턴스가 서로 달라도, 호출한 Bean이 동일하기 때문에 서로 비교했을 때 동일한 것을 알 수 있다.

 

Prototype

Singleton 범위와 반대되는 타입이 Prototype 범위라고 한다.

Prototype의 경우 개발자는 별도로 설정을 해줘야 하는데, application-context.xml에 Bean객체를 정의할 때 scope 속성을 명시해주면 된다.

 

위의 예제에서 application-context.xml에서 dependencyBean 속성에 scope를 추가해준다.

 

application-context.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"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
 		http://www.springframework.org/schema/beans/spring-beans.xsd">
	
	<bean id="injectionBean" class="scope.ex.InjectionBean"/>
	<bean id="dependencyBean" class="scope.ex.DependencyBean" scope="prototype">
		<constructor-arg ref="injectionBean"></constructor-arg>
		<property name="injectionBean" ref="injectionBean"/>
	</bean>
</beans>

 

결과 화면

scope 속성을 통해 prototype을 명시해주었기 때문에, 동일한 Bean을 가져오더라도 별도의 객체 형태로 생성하여 가져온다.