반응형
빈 스코프란
- 스프링 빈은 스프링 컨테이너의 시작과 함께 생성되어 스프링 컨테이너가 종료될 때까지 유지
- 스프링 빈이 기본적으로 싱글톤 스코프로 생성되기 때문
스프링이 지원하는 스코프
- 싱글톤 : 기본 스코프, 가장 넓은 범위의 스코프
- 프로토타입
- 프로토타입 빈의 생성과 의존관계 주입까지만 관여
- 매우 짧은 범위의 스코프
- 웹 관련 스코프
- request : 웹 요청이 들어오고 나갈 때까지 유지되는 스코프
- session : 웹 세션이 생성되고 종료될 때까지 유지되는 스코프
- application : 웹의 서블릿 컨텍스트와 같은 범위로 유지되는 스코프
빈 스코프는 다음과 같이 지정
- 컴포넌트 스캔 자동 등록
@Scope("prototype")
@Component
- 수동 등록
@Scope("prototype")
@Bean
PrototypeBean 클래스이름() {
return new 클래스이름();
}
프로토타입 스코프
- 싱글톤 스코프의 빈을 조회하면 항상 같은 인스턴스의 스프링 빈을 반환
- 프로토타입 스코프의 빈을 조회하면 스프링 컨테이너는 항상 새로운 인스턴스를 생성해서 반환
프로토타입 빈 vs 싱글톤 빈
싱글톤 빈 요청
- 싱글톤 스코프의 빈을 스프링 컨테이너에 요청
- 스프링 컨테이너는 관리하는 스프링 빈을 반환
- 같은 요청에는 같은 객체 인스턴스의 스프링 빈을 반환
프로토타입 빈 요청
- 프로토타입 스코프의 빈을 스프링 컨테이너에 요청
- 스프링 컨테이너는 요청이 올 때마다 프로토타입 빈을 생성하고, 필요한 의존관계 주입
- 생성된 빈은 클라이언에 반환되고 더 이상 관리되지 않는다.
정리하자면
- 스프링 컨테이너는 프로토타입 빈을 생성하고, 의존관계 주입, 초기화까지 만을 처리
- 클라이언트에 프로토타입 빈을 반환하고 더이상 관리하지 않는다.
- 프로토타입 빈을 관리할 책임은 프로토타입 빈을 받은 클라이언트에 있다.
- 프로토타입 빈은 반환하고 관리되지 않기 때문에 @PreDestroy 같은 종료 메서드가 호출되지 않는다.
프로토타입 스코프 - 싱글톤 빈과 함께 사용시 문제점
- 프로토타입과 싱글톤 빈을 함께 사용할 때 의도와 다르게 동작할 수 있음으로 주의가 필요
- 예시
- clientBean은 싱글톤이므로, 보통 스프링 컨테이너 생성 시점에 함께 생성되고, 의존관계도 주입
- clientBean은 의존관계 자동 주입을 사용, 주입 시점에 스프링 컨테이너에 프로토타입 빈을 요청
- 스프링 컨테이너는 프로토타입 빈을 생성해 clientBean에 반환
- 프로토타입 빈의 count 필드 값은 0이다.
- clientBean은 프로토타입 빈을 내부 필드에 보관(참조값을 보관)
- 클라이언트 A는 clientBean을 스프링 컨테이너에 요청해서 받는다.
- clientBean은 싱글톤이므로 항상 같은 객체가 반환
- 클라이언트 A는 clientBean.logic()을 호출
- clientBean은 prototypeBean의 addCount()를 호출하여 프로토타입 빈의 count를 증가
- prototypeBean의 count 값은 1이 된다.
- 클라이언트 B는 clientBean을 스프링 컨테이너에 요청
- clientBean은 싱글톤이므로 항상 같은 clientBean이 반환
- clientBean이 내부에 가지고 있는 프로토타입 빈은 이미 과거에 주입이 끝난 빈으로
클라이언트 B의 요청에 따라 새롭게 생성되는 빈이 아니다. - 때문에 클라이언트 B가 clientBean.logic()을 호출하면,
clientBean은 prototypeBean의 addCount()를 호출해서 프로토타입 빈의 count를 증가 - 원래 count 값이 1이었으므로 count 값은 2가 된다.
프로토타입 스코프 - 싱글톤 빈과 함께 사용 시 문제 해결법
ObjectFactory, ObjectProvider
- 의존관계를 외부에서 주입받는 것을 DI라고 한다.
- DI와 다르게 직접 필요한 의존관계를 찾는 것을 Dependency Lookup(DL) 의존관계 조회라 한다.
- ObjectProvider는 지정한 빈을 컨테이너에서 대신 찾아주는 DL 서비스를 제공한다.
- 과거에는 ObjectFactory가 있었는데, 여러 편의 기능을 추가해 ObjectProvider가 만들어졌다.
- 예시
- prototypeBeanProvider.getObject()를 통해서 항상 새로운 프로토타입 빈이 생성된다.
- ObjectProvider의 getObject()가 DL 기능을 제공한다.
- ObjectFactory와 ObjectProvider의 특징
- ObjectFactory : 기능이 단순, 별도의 라이브러리 필요 없음, 스트링에 의존
- ObjectProvider
- ObjectFactory에 비해 편의기능이 많다.
- 별도의 라이브러리 필요없음
- 스프링에 의존
JSR-330 Provider
- ObjectFactory와 ObjectProvider는 모두 스프링에 의존한다.
- JSP-330 Provider의 경우 자바 표준이기 때문에 스프링이 아닌 다른 컨테이너에서도 사용할 수 있다.
- 이 방식을 이용하려면 javax.inject:javax.inject:1 라이브러리를 gradle에 추가해야 한다.
- 예시
- provider의 get()을 호출하면 DL 기능을 이용할 수 있다.
- 자바 표준으로 기능이 단순하여 단위 테스트를 만들거나 mock 코드를 만들기 쉽다.
- 기능은 get() 메서드 하나로 매우 단순하다.
- 별도의 라이브러리가 필요하다.
그렇다면 new와 provider get()의 차이점은?
- provider와 get 메서드의 경우 스프링 컨테이너를 통해 해당 빈을 조회하고,
조회된 빈을 반환하는 역할을 한다. - new의 경우 새로운 객체를 반환하는 역할을 한다.
- 스프링 컨테이너를 통한다는 것을 제외하면 둘의 결과는 서로 비슷해 보인다.
- 그렇다면 차이점은 무엇일까?
- new의 경우 스프링 컨테이너를 통하지 않아 의존관계 주입이 안되고 필요한 초기화도 되지 않는다.
- provider.get()의 경우 스프링 컨테이너를 통해 의존관계 주입과 초기화가 가능하다.
- 그렇다면 provider.get()을 쓰는 게 항상 좋은 것일까?
- 그것은 아니다. 상황에 따라 적절하게 new를 사용해도 가능하다.
- 김영한 님의 우선순위 정리는 다음과 같다.(참고용)
- new로 문제를 해결할 수 있으면 new로 해결한다.
- 요청마다 항상 새로운 객체가 필요한데, new를 사용하면 의존관계(@Autowired) 주입이 불가하다.
의존관계 주입을 객체 생성 시점에 꼭 받아야 한다면 provider.get()을 활용하자.
웹 스코프
웹 스코프의 특징
- 웹 스코프는 웹 환경에서만 동작한다.
- 웹 스코프는 프로토타입과 다르게 스프링이 해당 스코프의 종료 시점까지 관리
- 따라서 종료 메서드가 호출된다.
웹 스코프의 종류
- request
HTTP 요청 하나가 들어오고 나갈 때까지 유지되는 스코프
각각의 HTTP 요청마다 별도의 빈 인스턴스가 생성되고 관리된다. - session
HTTP Session과 동일한 생명주기를 가지는 스코프 - application
서블릿 컨텍스트(SevletContext)와 동일한 생명주기를 갖는 스코프 - websocket
웹 소켓과 동일한 생명주기를 갖는 스코프
출처 : 인프런 김영한 님 스프링 강의
반응형
'내가 공부하려고 올리는 > 스프링' 카테고리의 다른 글
나는 ServiceImpl을 잘 활용했는가? (0) | 2022.07.11 |
---|---|
스프링 MVC와 계층형 아키텍처(Layered Architecture) (0) | 2022.07.11 |
빈 생명 주기 콜백 (0) | 2022.02.04 |
의존 관계 주입 (0) | 2022.02.03 |
컴포넌트 스캔 (0) | 2022.02.03 |
댓글