개발 기록
> [Spring] Bean Scope - 3. 프로토타입빈과 싱글톤 빈 함께 사용하기 (Proxy mode, Provider) 본문
> [Spring] Bean Scope - 3. 프로토타입빈과 싱글톤 빈 함께 사용하기 (Proxy mode, Provider)
1z 2024. 1. 24. 20:22
☞ protype scope : 해당 특정 Bean에 대한 요청이 이루어질 때마다 해당 Bean 의 새 인스턴스를 생성
☞ singleton scope : Spring 컨테이너에서 한 번 생성 되며, 컨테이너가 종료 시 해당 bean 제거
싱글톤 Bean이 다른 싱글톤 Bean 을 참조하거나 싱글톤이 아닌 Bean이 다른 싱글톤이 아닌 Bean을 참조하는 경우 일반적으로 하나의 Bean을 다른 Bean의 특성으로 정의하여 종속성을 처리한다. 이 때 Bean 간의 수명주기가 다르면 문제가 발생하는데 예로 들면 싱글톤 Bean A가 프로토타입 Bean B를 사용해야 한다고 가정했을 때이다. 아래에서 살펴보자
1. 프로토 타입 빈 종속성을 갖춘 싱글톤 빈
prototype scope bean 이 singleton scope bean 을 참조하는 경우 단 하나의 인스턴스를 가지는 빈을 참조해서 쓰기 때문에 문제가 되지 않지만 그 반대는 문제가 된다.
prototype scope bean 에 대한 종속성을 가진 singleton scope bean 을 사용하는 경우 prototype scope bean 의 새 인스턴스를 획득할 수 없는데 매번 같은 개체가 호출된다는 것을 말한다. 왜냐하면 Spring 컨테이너가 싱글톤 Bean을 인스턴스화하고 종속성을 주입하는 것이 한번 만 발생하기 때문이다. 한마디로 singleton 빈 안에 있는 prototype 빈도 최초로 주입된 채로 그대로 사용된다.
이에 대한 해결방법이 있다.
1. ProxyMode 사용
2. DL
1. Proxy Mode 사용
@Scope 어노태이션에 proxyMode = ScopedProxyMode.TARGET_CLASS 를 넣어준다.
☞ 인터페이스의 경우 => proxyMode = ScopedProxyMode.INTERFACES
@Component
@Scope(value = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class ProtoTypeBean {
}
ApplicationConxtext가 빈을 처음에 생성할 때 prototype 빈을 주입받는게 아니라 prototype 클래스를 상속받은 proxy 클래스를 만들어서 빈으로 등록하고 proxy 클래스에서 내부적으로 매번 새로운 prototype 빈을 사용한다.
2. Dependency Lookup Method Injection
Lookup method injection is the ability of the container to override methods on container-managed beans and return the lookup result for another named bean in the container.
★Dependency Lookup (DL, 의존성 검색) 이란?
필요한 시점에 직접 Spring Bean에 접근하기 위해 ApplicationContext, ObjectProvider, @Lookup, Provider 등을 이용하여 검색하는 것이다.
(1) ObjectProvider
- ObjectProvider의 getObject()를 호출하면 내부에서는 스프링 컨테이너를 통해 해당 빈을 찾아서 반환한다.
- 스프링에 의존하지만 별도 라이브러리는 필요 없다.
@Component
@Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON)
public class SingleScopeBean {
@Autowired
private ObjectProvider<PrototypeBean> provider;
public PrototypeBean getProto() {
return provider.getObject();
}
}
(2) JSR-330 Provider 이용
- javax.inject.Provider 라는 JSR-330 자바 표준 사용
- Provider의 get() 를 호출하면 내부에서는 스프링 컨테이너를 통해 해당 빈을 찾아서 반환한다.
- 라이브러리 추가 필요
javax.inject:javax.inject:1 // build.gradle에 추가
@Component
@Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON)
public class SingleScopeBean {
@Autowired
private Provider<PrototypeBean> provider;
public PrototypeBean getProto() {
return provider.get();
}
}
▶ Dependency Lookup(DL)을 언제 사용하는가? (javax.inject Document)
- 여러 인스턴스를 검색해야 하는 경우
- 인스턴스를 지연 혹은 선택적으로 찾아야 하는 경우
- 순환 종속성을 깨기 위해서
- 스코프에 포함된 인스턴스로부터 더 작은 범위의 인스턴스를 찾아 추상화 하기 위해서 사용한다.
'Spring' 카테고리의 다른 글
| > [Spring Event] Spring Event 적용 - @TransactionalEventListener, @Async (0) | 2024.01.19 |
|---|---|
| > [Spring Event] Spring Event 비동기 처리 (0) | 2024.01.19 |
| > [Spring] Bean Scope - 2. 사용자 정의 Bean Scope (0) | 2024.01.18 |
| > [Spring] Bean Scope - 1. 개념과 사용 방법(singleton, prototype, request) (0) | 2024.01.18 |
| > [Spring Event] Event 개념과 Spring Event 사용법 (0) | 2024.01.16 |