빈 스코프

wangjh789·2022년 7월 29일
0

빈 스코프

빈으로써 존재할 수 있는 범위를 의미한다.(default는 싱글톤)
(빈 저장소에서 관리하는 범위)

  • 싱글톤 : 스프링 컨테이너와 생명주기가 같음
  • 프로토타입 : 빈의 생성과 의존관계 주입까지만 관여
    (초기화 메서드는 호출, 종료메서드는 호출이 되지 않음)

웹 관련 스코프

  • request : 웹 요청이 들어오고 나갈 때 까지 유지되는 스코프
  • session : 웹 세션이 생성되고 종료될 때까지 유지
  • application : 웹 서블릿 컨텍스트와 같은 범위

프로토타입 스코프

싱글톤 빈을 조회하면 스프링 컨테이너에는 항상 같은 인터페이스의 스프링 빈을 반환
프로토타입 빈을 조회하면 스프링 컨테이너는 새로운 인스턴스를 생성해서 반환
주로 초기화까지 완료된 인스턴스를 받고 싶을 때 사용, 거의 사용하지 않는다.

Assertions.assertThat(singletonBean1).isSameAs(singletonBean2);
a.isSameAs(b) 는 a==b 를 의미

싱글톤 빈은 스프링 컨테이너 생성 시점에 초기화 메서드가 실행
프로토타입 빈은 스프링 컨테이너에서 빈을 조회할 때 생성되고 초기화 메서드도 실행

싱글톤 빈과 프로토타입 빈을 함께 사용 시

싱글톤 빈이 프로토타입 빈을 내부 필드로 가지고 있다고 가정.
싱글톤 빈이 프로토타입 빈의 참조를 가지고 있어 프로토타입의 생존주기가 싱글톤 빈 스코프와 같아진다.

	@Scope("singleton")
    class ClientBean {
        private final PrototypeBean prototypeBean;

        @Autowired
        public ClientBean(PrototypeBean prototypeBean) {
            this.prototypeBean = prototypeBean;
        }

        public int login() {
            prototypeBean.addCount();
            return prototypeBean.getCount();
        }
    }

DL을 이용한 해결방안

의존관계를 외부에서 주입받는 것은 DI, 직접 찾아서 사용하는 것은 DL(dependency lookup)

	class ClientBean {
        
        public int logic() {
            AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(PrototypeBean.class);
            PrototypeBean prototype = ac.getBean(PrototypeBean.class);
            return prototype.getCount();
        }
    }

메소드를 실행할때 마다 직접 스프링 컨텍스트에서 해당 프로토타입 빈을 찾아 새로운 빈을 생성해 사용한다.
컨텍스트를 주입받으므로 스프링 종속적이고, 단위테스트도 쉽지 않다.

그래서 스프링 컨텍스트에서 직접 찾는 것보다 대신 찾아주는 DL 정도의 기능만 제공하는 무언가를 사용해야 한다.

ObjectProvider, ObjectFactory

		@Autowired
        private ObjectProvider<PrototypeBean> provider;

        public int login() {
            PrototypeBean prototypeBean = provider.getObject();
            prototypeBean.addCount();
            return prototypeBean.getCount();
        }

ObjectProvider는 컨텍스트에서 해당 빈을 DL해주는, 스프링 의존적인 기능이지만 기능이 간단해서 괜찮다.
필요한 정도의 DL을 대신 해주는 느낌
ObjectFactory의 자식이 ObjectProvider

JSR-330 Provider

스프링에 의존하지 않는 330자바 표준을 사용하는 방식

gradle 추가 implementation 'javax.injdet:javax.inject:1'
import javax.inject.Provider;

		@Autowired
        private Provider<PrototypeBean> provider;

        public int login() {
            PrototypeBean prototypeBean = provider.get();
            prototypeBean.addCount();
            return prototypeBean.getCount();
        }

ObjectProvider와 사용방법이 같다.

profile
기록

0개의 댓글