-
Spring bean 정리(3)_Spring Bean 스코프Spring Framework 2023. 8. 13. 15:49
bean scope
- 빈이 존재할 수 있는 범위
Singleton scope
- 기본 스코프, 스프링 컨테이너의 시작과 종료까지 유지되는 가장 넓은 범위의 스코프
- Singleton bean은 컨테이너 생성 시점에 같이 생성되고 초기화된다.
- 생성된 하나의 인스턴스는 Spring Beans Cache에 저장되고, 해당 빈에 대한 요청과 참조가 있으며 캐시된 객체를 반환한다. 하나만 생성되기 때문에 동일 참조를 보장한다.
- 모든 빈은 스코프가 명시적으로 지정되지 않으면 싱글톤이다.
- 대상 클래스에 @Scope(”singletone”) 을 붙이면 된다.
- 각각 다른 요청에서 boardService bean(Singleton scope의 bean)을 요청하면 스프링 컨테이너는 동일한 boardService bean을 반환한다.
Prototype scope
- 짧은 범위의 스코프
- Prototype bean을 요청하면 스프링 컨테이너는 항상 새로운 Prototype bean을 생성하고 필요한 의존관계를 주입해 반환한다.
- Prototype bean이 생성된 이후에는 스프링 컨테이너에서 관리하지 않아, 관리에 대한 책임이 클라이언트에게 있다.
- Prototype bean은 스프링 컨테이너에서 빈을 조회할 때 생성되고 초기화 메서드도 실행된다.
- 대상 클래스에 Scope("prototype") 을 붙이면 된다.
* 싱글톤 객체가 프로토 타입 객체를 가지고 있는 경우 생기는 문제점
- 싱글톤 빈으로 생성되는 시점에 프로토 타입 빈이 생성되어 들어오기 때문에 싱글톤 빈 내부의 프로토 타입 빈을 호출하게 되면 매번 같은 값을 가져 온다.
- 해결방법
- Provider
- @Scope의 proxyMode 설정
Provider
- logic() 메소드를 호출할 때마다 다른 PrototypeBean 인스턴스가 호출된다. Provider는 자바 표준이라서 스프링에 독립적이라는 장점이 있다.
@Component class ClientBean { @Autowired private Provider<PrototypeBean> provider; //javax.inject 하위 클래스로 import해야함 public int logic() { PrototypeBean prototypeBean = provider.get(); // 컨테이너에 빈 요청 prototypeBean.addCount(); return prototypeBean.getCount(); } }@Scope의 proxyMode 설정
- 해당 객체에 @Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_ClASS) 설정
- 적용대상이 클래스면 TARGET_CLASS를 선택, 적용대상이 인터페이스면 INTERFACES를 선택
웹 관련 scope
- 스프링이 해당 스코프의 종료 시점까지 관리한다. 따라서 종료 메서드가 호출된다.
- 스프링 빈 등록 시 웹 스코프를 그대로 주입받으면 오류가 발생한다.
- request 스코프의 경우 HTTP 요청이 올 때 새로 생성되고 응답하면 사라지기 때문에, 싱글톤 빈이 생성되는 시점에는 아직 생성되지 않음 (의존관계 주입이 불가능하다.)
* 의존 관계 주입 불가능을 해결하는 방법 = @Scope의 proxyMode 설정
@Component @Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_ClASS) public class MyLogger { /* 적용대상이 클래스면 TARGET_CLASS를 선택 적용대상이 인터페이스면 INTERFACES를 선택 */ // code... }- MyLogger의 가짜 프록시 클래스를 만들어두고 HTTP request와 상관없이 가짜 프록시 클래스를 다른 빈에 미리 주입해둘 수 있다.
- 스프링 컨테이너는 CGLIB라는 바이트코드 조작 라이브러리를 사용해서, 해당 웹 스코프 빈 클래스를 상속하는 가짜 프록시 객체를 생성한다.
- 가짜 프록시 객체는 요청이 오면 그때 내부에서 진짜 빈을 요청하는 위임 로직이 들어있다.
- 가짜 프록시 객체는 내부에 진짜 myLogger를 찾는 방법을 알고 있어, 클라이언트가 myLogger.logic()을 호출하면 사실은 가짜 프록시 객체의 메서드를 호출한다.
- 가짜 프록시 객체는 request 스코프의 진짜 myLogger.logic()을 호출한다.
- 가짜 프록시 객체는 원본 클래스를 상속받아서 만들어졌기 때문에 이 객체를 사용하는 클라이언트 입장에서는 원본인지 아닌지도 모르게 동일하게 사용할 수 있다(다형성)
- 웹 scope 종류
- request : HTTP 요청 하나가 들어오고 나갈 때까지 유지되는 스코프, 각각의 HTTP 요청마다 별도의 빈 인스턴스가 생성되고 관리된다.
- session : HTTP Session과 동일한 생명주기를 가지는 스코프
- application : 서블릿 컨텍스트(ServletContext)와 동일한 생명주기를 가지는 스코프
- websocket : 웹 소켓과 동일한 생명주기를 가지는 스코프
출처)
https://steady-coding.tistory.com/594
https://code-lab1.tistory.com/186'Spring Framework' 카테고리의 다른 글
스프링 컨테이너에 대한 개념 (0) 2023.10.04 스프링 프레임워크(spring framework)에 대한 기본 개념 (0) 2023.10.04 Spring bean 정리(2)_Bean 생성과 singleton (0) 2023.08.13 Spring bean 정리(1)_bean 등록 (0) 2023.08.13 spring MVC & servlet 정리 (0) 2023.08.13