프로토타입 빈과 싱글톤 빈 - 해결법

초보개발·2021년 12월 20일
0

Spring

목록 보기
27/37

해결책 : Provider

싱글톤 스코프 빈과 프로토타입 스코프 빈을 같이 사용할 때 사용할 때마다 항상 새로운 프로토타입 스코프의 빈이 생성되지 않는다는 문제점이 있었다. 어떻게 하면 이 문제를 해결하고 올바른 의도대로 사용할 수 있을까?

1. 스프링 컨테이너에게 요청

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

static class ClientBean {
    @Autowired
    private ApplicationContext ac;
    
    public int logic() {
        PrototypeBean prototypeBean = ac.getBean(PrototypeBean.class);
        ...
    }
}
  • ac.getBean()으로 항상 새로운 프로토타입 빈이 생성된다.
  • 의존관계를 외부에서 주입받는 방식이 아닌 직접 필요한 의존관계를 찾는 것을 DL(Dependency Lookup, 의존관계 탐색)이라고 한다.
  • 스프링의 ApplicationContext 전체를 주입받게 되면, 스프링 컨테이너에 종속적인 코드가 되며 단위 테스트도 어려워지게 된다.
  • 프로토타입 빈을 컨테이너에서 대신에 찾아줄 수 있는 DL 정도의 기능만 제공하는 것만 있으면 된다.

2. ObjectFactory, ObjectProvider

ObjectProvider는 지정한 빈을 컨테이너에서 대신 찾아주는 DL 기능을 제공해준다. 기존에ObjectFactory가 있었는데 이 인터페이스를 상속받고 여러가지 기능을 추가하여 만든 것이 ObjectProvider이다.

static class ClientBean {

        @Autowired
        private ObjectProvider<PrototypeBean> prototypeBeanProvider;

        public int logic() {
            PrototypeBean prototypeBean = prototypeBeanProvider.getObject();
            prototypeBean.addCount();
            return prototypeBean.getCount();
        }
    }
  • prototypeBeanProvider.getObject()으로 항상 새로운 프로토타입 빈이 생성된다.
  • ObjectProvider의 getObject() 메서드를 호출하면 내부에서 스프링 컨테이너를 통해 해당 빈을 찾아 반환한다.( DL )
  • 스프링이 제공하는 기능을 사용하고 있지만, 기능이 단순하므로 단위테스트나 mock 코드를 만들기 훨씬 쉬워진다.

3. JSR-330 Provider

스프링에 의존하지 않고 javax.inject.Provider라는 자바 표준을 사용하는 방법이다. 이 방법을 사용할 경우, build.gradle에 dependency 항목에 추가해주면 되는데, implementation 'javax.inject:javax.inject:1' 추가하면 된다.

static class ClientBean {

    @Autowired
    private Provider<PrototypeBean> prototypeBeanProvider;

    public int logic() {
        PrototypeBean prototypeBean = prototypeBeanProvider.get();
        prototypeBean.addCount();
        return prototypeBean.getCount();
    }
}
  • Provider.get()으로 항상 새로운 프로토타입 빈이 생성된다.
  • provider의 get() 메서드를 호출하면 내부에서는 스프링 컨테이너를 통해 해당 빈을 찾아 반환한다. ( DL )
  • 자바 표준이며 기능도 단순하므로 단위테스트를 만들거나 mock 코드를 만들기 쉽다.
  • 별도의 라이브러리 추가가 필요하지만, 자바 표준이라서 스프링이 아닌 다른 컨테이너에서도 사용 가능하다.

프로토타입 스코프의 빈을 사용할 때

매번 사용할 때마다 의존관계 주입이 완료된 새로운 객체가 필요하면 사용하면 된다. 하지만 실무에서는 싱글톤 빈으로 대부분 해결이 되므로 프로토타입 빈을 직접적으로 사용하는 경우는 거의 없다.

OjbectProvider or JSR-330 Provider ?

  • ObjectProvider, JSR303 Provider는 프로토타입말고도 DL이 필요한 경우에는 언제든지 사용할 수 있다.
  • 따라서 어느 것을 사용할 것인지 고민이 생기는데, ObjectProvider는 DL에 관한 기능을 많이 제공해주며 스프링 외에 별도의 의존관계 추가가 필요없다. 만약 코드를 스프링이 아닌 다른 컨테이너에서도 사용할 수 있게 해야한다면 자바 표준인 JSR-330 Provider를 사용해야 한다.(거의 그럴 일이 없다)

0개의 댓글