Spring

TIL-8 빈 스코프 프로토타입-2

다오__ 2023. 5. 22. 21:16

이전편

https://dao-blog.tistory.com/14

 

TIL-7 빈 스코프 프로토타입-1

지금까지 우리는 스프링 빈이 스프링 컨테이너의 시작과 함께 생성되어서 스프링 컨테이너가 종료될 때까지 유지된다고 배웠다 이것은 스프링 빈이 기본적으로 싱글톤 스코프로 생성되기 때문

dao-blog.tistory.com

 

 

하지만

너무 지저분하다..그리고 프로토타입 빈이 새로 생성되기는 하지만, 싱글톤 빈과 함께 계속 유지되는 것이 문제다.

 

아마 원하는 이런 아닐 것이다. 프로토타입 빈을 주입 시점에만 생성시키는 것이 아니라 사용할 때마다 새로 생성해서 사용하는 것을 원할 것이다.

 

 

 

프로토타입 스코프 - 싱글톤 빈과 함께 사용시 Provider로 문제해결

  싱글톤 빈과 프로토타입 빈을 함께 사용할 때, 어떻게하면 사용할 때마다 항상 새로운 프로토타입 빈을 생성할 있을까?

 

스프링 컨테이너에 요청

가장 간단한 방법은 싱글톤 빈이 프로토타입을 사용할 마다 스프링 컨테이너에 새로 요청하는 것이다.

 

 실행해보면 ac.getBean()을 통해서 항상 새로운 프로토타입 빈이 생성되는 것을 확인 있다.

 

 의존관계를 외부에서 주입받는게 아니라 이렇게 직접 필요한 의존관계를 찾는 것을 Dependency Lookup (DL) 의존관계 조회(탐색)이라고 한다.

 

 그런데 이렇게 스프링의 애플리케이션 컨텍스트 전체를 주입 받게 되면, 스프링 컨테이너에 종속적인 코드가 되고, 단위테스트도 어려워진다…

 

 지금 필요한 기능은 지정한 프로토타입 만을 스프링컨테이너에서 대신 찾아주는 DL정도의 기능만 제공하는 무언가만 있으면 된다.

 

ObjectFactory, ObjectProvider

지정한 빈을 컨테이너에서 대신 찾아주는 DL서비스를 제공하는 것이 바로 ObjectProvider이다.

 

코드를 수정해보자

 

ClientBean 클래스에 ObjectProvider를 사용

테스트 이기에 필드주입을 하였다.

 

이후 logic메서드에 아래와같이 추가한다

 

싱글톤 ClientBean에서 두개의 PrototypeBean을 생성한 것을 있다!

 

예전에 ObjectFactory를 사용하였지만 이를 상속받는 ObjectProvider를 편의성이 추가되어 사용된다.

 

실행해보면 prototypeBeanProvider.getObject()를 통해서 항상 새로운 프로토타입 빈이 생성되는 것을 확인  있다.

ObjectProvider의 getObject()를 호출하면 내부에서는 스프링 컨테이너를 통해 해당 빈을 찾아서 반환한다.("DL")

 

스프링이 제공하는 기능을 사용하지만, 기능이 단순하므로 단위테스트를 만들거나 mock 코드를 만들기는 훨씬 쉬워진다.

ObjectProvider는 지금 필요한 DL정도의 기능만 제공한다.

 

특징

ObjectFactory :  기능이 단순, 별도의 라이브러리 필요 없음, 스프링에 의존

ObjectProvider :  ObjectFactory 상속, 옵션, 스트림처리등 편의기능이 많고 별도의 라이브러리 필요 없음, 스프링에 의존

 

하지만 여전히 스프링에 의존적이다.

 

 

JSR-330 Provider

마지막 방법은 javax.inject.Provider 라는 JSR-330 자바 표준을 사용하는 방법이다.

방법을 사용하려면 javax.inject:javax.inject:1 라이브러리를 gradle에 추가해야한다.

 

build.gradle에 추가하자

 

 

정말 심플하다..

 

ClientBean을 수정해주자

 

 실행해보면 provider.get()을 통해서 항상 새로운 프로토타입 빈이 생성되는 것을 확인 있다.

provider get()을 호출하면 내부에서는 스프링 컨테이너를 통해 해당 빈을 찾아서 반환한다("DL")

자바 표준이고 기능이 단순하기에 단위테스트를 만들거나 mock코드는 만들기는 훨씬 쉽다.

Provider는 지금 필요한 DL정도의 기능만 제공한다.