빈 스코프

Sin·2024년 6월 29일

스코프는 번역 그대로 빈이 존재할수 있는 범위를 뜻한다.

스프링이 지원하는 스코프

  • 싱글톤: 기본 스코프, 스프링 컨테이너의 시작과 종료까지 유지되는 가장 넓은 범위의 스코프이다.
  • 프로토타입: 스프링 컨테이너는 프로토타입 빈의 생성과 의존관계 주입까지만 관여하고 더는 관리하지 않는 매우 짧은 범위의 스코프이다.
  • 웹 관련 스코프
    request: 웹 요청이 들어오고 나갈때 까지 유지되는 스코프이다.
    session: 웹 세션이 생성되고 종료될 때 까지 유지되는 스코프이다.
    application: 웹의 서블릿 컨텍스트와 같은 범위로 유지되는 스코프이다.

프로토타입 빈의 특징 정리

  • 스프링 컨테이너에 요청할 때 마다 새로 생성된다.
  • 스프링 컨테이너는 프로토타입 빈의 생성과 의존관계 주입 그리고 초기화까지만 관여한다.
  • 종료 메서드가 호출되지 않는다.
  • 그래서 프로토타입 빈은 프로토타입 빈을 조회한 클라이언트가 관리해야 한다. 종료 메서드에 대한 호출도 클라이언트가 직접 해야한다.
  • 프로토타입 빈은 더이상 참조되는 곳이 없을 때 가비지 컬렉션 대상이 됨

싱글톤 스코프가 참조하는 프로토타입 빈은 참조 객체 이다.

여러 빈에서 같은 프로토타입 빈을 주입 받으면, 주입 받는 시점에 각각 새로운 프로토타입 빈이 생성된다.

예를 들어서 clientA, clientB가 각각 의존관계 주입을 받으면 각각 다른 인스턴스의 프로토타입 빈을 주입 받는다.

프로토타입 빈을 이렇게 까지 공부할 필요가 있을까?... 1시간이나 들여서?...

Request Scope

  • 웹 라이브러리가 없으면 AnnotationConfigApplicationContext 기반으로 애플리케이션을 구동 되고 웹 라이브러리가 추가되면 AnnotationConfigServletWebServerApplicationContext 를 기반으로 애플리케이션을 구동한다.

궁금했던 내용

@Component
@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class MyLogger {

}
  • proxyMode
    적용 대상이 인터페이스가 아닌 클래스면 TARGET_CLASS 를 선택
    적용 대상이 인터페이스면 INTERFACES 를 선택
  • CGLIB라는 라이브러리로 내 클래스를 상속 받은 가짜 프록시 객체를 만들어서 주입한다.

  • @Scope 의 proxyMode = ScopedProxyMode.TARGET_CLASS) 를 설정하면 스프링 컨테이너는 CGLIB 라는 바이트코드를 조작하는 라이브러리를 사용해서, MyLogger를 상속받은 가짜 프록시 객체를 생성한다.

  • 결과를 확인해보면 우리가 등록한 순수한 MyLogger 클래스가 아니라 MyLoggerEnhancerBySpringCGLIB 이라는 클래스로 만들어진 객체가 대신 등록된 것을 확인할 수 있다.

  • 그리고 스프링 컨테이너에 "myLogger"라는 이름으로 진짜 대신에 이 가짜 프록시 객체를 등록한다. ac.getBean("myLogger", MyLogger.class) 로 조회해도 프록시 객체가 조회되는 것을 확인할 수 있다.

  • 그래서 의존관계 주입도 이 가짜 프록시 객체가 주입된다

특징 정리

  • Provider를 사용하든, 프록시를 사용하든 핵심 아이디어는 진짜 객체 조회를 꼭 필요한 시점까지 지연처리 한다는 점이다.

출처 김영한의 스프링 로드맵 - 스프링 핵심원리 기본편

0개의 댓글