[기본기] 9-3. Provider

khyojun·2022년 10월 13일
1
post-thumbnail

본 게시글은 김영한님의 스프링 핵심 원리 기본편을 정리한 글입니다.


이전 시간 싱글톤 빈과 프로토타입의 빈을 같이 사용하였을때 문제점을 알아봤는데 이를 해결하기위하여 어떻게 해야할 지 한 번 알아보자.

📌 1. 스프링 컨테이너에 다시 요청하기.

싱글톤 빈이 프로토타입을 사용할때마다 계속 다시 요청하여주면 된다고 한다.

public class PrototypeProviderTest {

    @Test
    void providerTest(){
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(ClientBean.class, PrototypeBean.class);

        ClientBean bean = ac.getBean(ClientBean.class);
        int count1= bean.logic();
        Assertions.assertThat(count1).isEqualTo(1);


        ClientBean bean2 = ac.getBean(ClientBean.class);
        int count2= bean.logic();
        Assertions.assertThat(count2).isEqualTo(1);
    }

    static class ClientBean{
        @Autowired
        private ApplicationContext ac; DL -> DependencyLookup
        
        public int logic(){
            PrototypeBean bean = ac.getBean(PrototypeBean.class);
            bean.addCount();
            return bean.getCount();
        }
    }

   @Scope("prototype")
    static class PrototypeBean{
        private int count =0;

        public void addCount(){
            count++;
        }

        public int getCount() {
            return count;
        }

        @PostConstruct
        public void init(){
            System.out.println("PrototypeBean.init");
        }

        @PreDestroy
        public void destroy(){
            System.out.println("PrototypeBean.destroy");
        }
    }

여기서 우리가 봐야할 것은 다음 코드이다.

        @Autowired
        private ApplicationContext ac; DL -> DependencyLookup
        
        public int logic(){
            PrototypeBean bean = ac.getBean(PrototypeBean.class);
            bean.addCount();
            return bean.getCount();
            }

여기서 여기서 이전에는 AutowiredPrototypeBean과 연결하여 사용을 햇었는데 이번에는 스프링 컨테이너를 의존관계를 부여하여줬다 이러한 것은 DL(Dependency Lookup) 의존관계 조회(탐색) 이라고 한다고 한다.

DL : 의존관계 조회(탐색)

  • DL(Dependency Lookup) : 의존대상(사용할 객체)을 검색(lookup)을 통해 반환받는 방식
  • 내가 직접 필요한 의존관계를 찾는 것.
  • ac.getBean(PrototypeBean.class);을 통하여서 직접 찾게 되었다.
  • 그치만 ApplicationContext를 주입받으면 컨테이너에 종속적인 코드가 된다고 한다. -> 이렇게 되면 단위테스트가 어려운...
  • 이 단점을 해결하기위해서는 컨테이너에서 우리가 원하는 프로토타입의 빈을 찾기만 하면 된다.

📌 2. ObjectProvider, ObjectFactory 사용

위에서 얘기했듯이 내가 찾고싶은 빈을 컨테이너에서 대신 찾아주는 DL 서비스를 ObjectProvider가 제공을 하여준다. 옛날에는 ObjectFactory가 있었는데 여기에 기능을 추가한것인 ObjectProvider가 만들어졌다고 한다.

  static class ClientBean{
        @Autowired
        private ObjectProvider<PrototypeBean> prototypeBeanObjectProvider; ObjectProvider 스프링에 의존
        
        
        public int logic(){
           PrototypeBean prototypeBean = prototypeBeanObjectProvider.getObject();
            prototypeBean.addCount();
            return prototypeBean.getCount();
        }
    }

ObjectFactory : 기능이 단순하고 별도의 라이브러리가 없음, 스프링에 의존함
ObjectProvider : ObjectFactory의 상속,옵션, 스트림 처리등 편의 기능이 많고, 별도의 라이브러리 필요 없음, 스프링에 의존

이전 코드와 비교하였을때 이제 DL을 ObjectProvider<PrototypeBean>을 통하여서 조회를 하여주고 밑에서 getObject를 활용하여서 빈을 반환시켰다.
그치만... 이 ObjectProvider와 ObjectFactory는 스프링에서 의존 기능이다. 그말인즉슨 다른 프레임워크에서는 이 기능을 활용하기에는 어려울 거 같다.

📌 3. JSR-330 Provider

위 마지막에서 언급하듯이 ObjectProvider는 스프링에 의존적이다. 그래서 자바 표준으로도 Provider라는 기능을 제공한다. 위 기능은 javax.inject.Provider를 import하면 된다.

  static class ClientBean{
        @Autowired
        private Provider<PrototypeBean> prototypeBeanProvider;   // Provider 자바 표준이므로 다른 프레임워크에서도 사용가능, get()하나로 되게 단순
        
        
        public int logic(){
            PrototypeBean prototypeBean = prototypeBeanProvider.get();
            prototypeBean.addCount();
            return prototypeBean.getCount();
        }
    }
    
    
    
  • Provider를 통하여서는 get()을 활용하여 DL을 하게 된다.
  • 별도의 라이브러리가 필요하다.
  • 스프링에 의존적이지 않아 다른 프레임워크에서도 사용이 가능하다.

오늘 찾아보게 이렇게 3가지의 방법으로 각각의 빈 스코프가 겹치게 될때 해결하는것을 보게 되었는데 결론적으로는 나중에 사용하게 될 것은 Provider를 주로 사용하게 될 거 같다. 강의에서는 마지막에 정리를 하실때 이런 말씀을 해주셨다.

프로토타입 빈을 언제 사용할지 한 번 생각을 해보면 DI가 완료된 새로운 객체가 필요하면 사용하게 된다. 그런데 실무에서는 개발을 하게 되었을때 싱글톤 빈으로 대부분의 문제를 해결할 수 있기 때문에 프로토타입 빈을 직접적으로 사용하는 일은 매우 드물게 된다.
DL이 필요한 경우에는 언제든지 ProviderObjectProvider를 사용하면 된다.

오늘의 결론

DL을 하기 위하여서 Provider, ObjectProvider를 잘 활용하자.

출처

  1. 김영한님의 스프링 핵심 원리 기본편(https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8)
profile
코드를 씹고 뜯고 맛보고 즐기는 것을 지향하는 개발자가 되고 싶습니다

0개의 댓글