본문 바로가기
  • 실행력이 모든걸 결정한다
Spring Series/Spring Framework

[Spring] Prototype Bean

by 김코더 김주역 2022. 6. 23.
반응형

스프링이 관리하는 bean은 기본적으로 singleton으로 관리된다. 그리고 singleton은 bean의 scope들 중 하나이기 때문에 설정을 통해 scope를 변경할 수도 있다.

※ scope : Spring이 관리하는 bean의 관리 범위를 의미하며, 하나의 scope 안에서는 매번 같은 오브젝트를 가져온다.

Bean의 scope로는 singleton, prototype, request, session, globalSession, application이 있는데, 이번 포스팅에서는 scope가 prototype인 bean의 특징과 여러가지 사용 방법에 대해 알아보자. 

 

먼저, bean의 scope는 다음과 같이 설정할 수 있다.

xml 방식

<bean id="..." class="..." scope="singleton">
	...
</bean>

Annotation 방식

@Component
@Scope("singleton")
public class ... {}

 

 

 

1. Prototype bean의 특징

- Bean을 요청할 때마다 새로운 오브젝트를 반환한다. 즉, new로 오브젝트를 생성하는 것을 대신할 수 있다.

- 스프링이 초기 생성 시에만 관여하고, 이미 제공된 bean은 스프링에 의해 더 이상 관리되지 않는다.

- 매번 새로운 오브젝트가 필요하면서 DI를 통해 다른 bean을 사용할 수 있어야 하는 경우에 유용하다. DI 하는 오브젝트도 bean으로 등록되어 있어야 하기 때문이다. ★

 

 

 

2. Prototype bean의 DL 전략

- Prototype bean을 가져오기 위해, 유일한 bean 오브젝트를 받아오는 DI 방식을 사용하는 것은 적합하지 않다. 대신, ApplicationContext에 있는 bean을 받아오기 위해 컨테이너가 제공하는 API를 이용하는 DL(Dependency Lookup) 방식을 사용해야 한다.

 

1) ApplicationContext 또는 BeanFactory 직접 이용하기

- ApplicationContext 또는 BeanFactory를 직접 DI 받아서 getBean() 메소드를 직접 호출하는 방법이다.

- XML만을 사용한다면 ApplicationContextAware 또는 BeanFactoryAware를 이용해도 된다.

ServiceRequest serviceRequest = context.getBean(ServiceRequest.class);

 

 

2) ObjectFactory와 ObjectFactoryCreatingFactoryBean 이용하기

- ObjectFactory는 spring이 제공하는 오브젝트 팩토리 빈 인터페이스다. 팩토리 빈이란, 특정 오브젝트를 요구할 때 오브젝트를 생성하거나 가져오는 방식을 신경쓰지 않도록 중간에서 역할하는 오브젝트를 뜻한다.

- ObjectFactoryCreatingFactoryBean도 spring이 제공하는 클래스로, ObjectFactory 인터페이스를 구현한 클래스다. 먼저, ObjectFactoryCreatingFactoryBean을 등록하는 방법은 다음과 같다.

Xml 등록

<bean id="serviceRequestFactory" class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean">
    <property name="targetBeanName" value="serviceRequest" />
</bean>

Java 등록

@Configuration
public class ObjectFactoryConfig {
    @Bean
    public ObjectFactoryCreatingFactoryBean serviceRequestFactory(){
        ObjectFactoryCreatingFactoryBean factoryBean = new ObjectFactoryCreatingFactoryBean();
        factoryBean.setTargetBeanName("serviceRequest");
        return factoryBean;
    }
}

그리고, ObjectFactory 객체를 DI 받고 팩토리가 생성해주는 오브젝트를 받아오는 방법은 다음과 같다.

@Resource // ObjectFactory는 인터페이스이므로 여러 타입이 있을 수 있기 때문에 이름으로 bean을 지정한다.
private ObjectFactory<ServiceRequest> serviceRequestFactory;
ServiceRequest serviceRequest = this.serviceRequestFactory.getObject();

 

 

3) ServiceLocatorFactoryBean

- Spring이 제공하는 ObjectFactory를 사용하는 것을 원하지 않을 경우에는 자신이 직접 factory 인터페이스를 만들어도 된다. 물론 메소드 이름도 마음대로 지어도 된다.

package a.b.c;
public interface ServiceRequestFactory {
    public ServiceRequest getServiceFactory();
}

- FactoryBean을 등록할 때는 ServiceLocatorFactoryBean의 serviceLocatorInterface property에 직접 만든 팩토리 인터페이스를 패키지를 포함하여 지정하면 된다. bean의 id는 필요 없다.

<bean class="org.springframework.beans.factory.config.ServiceLocatorFactoryBean">
    <property name="serviceLocatorInterface" value="a.b.c.ServiceRequestFactory" />
</bean>

- 직접 등록한 팩토리 인터페이스는 바로 @Autowired로 가져올 수 있다.

@Autowired ServiceRequestFactory serviceRequestFactory;

 

 

4) 메소드 주입

- Spring API에 의존적이지 않은 방식이다.

- 다음과 같이 추상 메소드를 작성해두고 bean을 가져오는 메소드를 런타임 시에 반영해주는 방법이다.

abstract public ServiceRequest getServiceRequest();

※ 추상 메소드를 가지는 클래스도 추상 클래스로 정의 되어야 한다.

- 이 추상클래스를 bean으로 등록하면 되는데, <lookup-method>의 name에는 추상 메소드의 이름을, bean에는 가져올 bean의 이름을 작성해주면 된다.

<bean id="serviceRequestController" class="a.b.c.ServiceRequestController">
    <lookup-method name="getServiceRequest" bean="serviceRequest"/>
</bean>

 

 

5) Provider

- ObjectFactory와 유사하게 타입 파라미터를 사용하고, FactoryBean을 bean으로 등록할 필요가 없는 편리한 방식이다.

- Provider 인터페이스는 javax.inject에 포함되어 있다.

- Provider를 DI 되도록 지정만 해주면 spring이 자동으로 Provider의 구현 오브젝트를 주입해준다.

@Autowired Provider<ServiceRequest> serviceRequestProvider;

- Bean은 Provider의 get() 메소드로 불러오면 된다.

ServiceRequest serviceRequest = this.serviceRequestProvider.get();

 

 

+ 추가 개념)

- Prototype 외에도 DL 방식이 필요한 경우라면 위와 같은 방법들을 사용할 수 있다. 

 

 

● 참고 자료 : 토비의 스프링 3.1 Vol.2

반응형

'Spring Series > Spring Framework' 카테고리의 다른 글

[Spring] Bean의 id와 name  (0) 2022.06.23
[Spring] Scope Proxy  (0) 2022.06.23
[Spring] RestTemplate 한글 깨짐 해결방법  (0) 2022.06.22
[Spring] SpEL  (0) 2022.06.21
[Spring] Collection 타입을 XML로 작성하기  (0) 2022.06.21

댓글