Notice
Recent Posts
Recent Comments
Link
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Archives
Today
Total
관리 메뉴

개발자되기 프로젝트

Provider, ObjectProvider 본문

인프런/[인프런] Spring 핵심원리 이해

Provider, ObjectProvider

Seung__ 2021. 8. 1. 13:17

싱글톤 빈과 프로토 빈 함께 사용 시 발생하는 문제점 해결해보자.

 

이 전 글에서 생긴 문제점은 다음과 같다.

  • 프로토 타입 빈은 요청할 때 마다 새로 생성하고 싶다.
  • 하지만 싱글톤 빈 생성시 프로토타입이 주입이된다.
  • 따라서 싱글톤 빈 내부의 프로토타입은 새로 생성되지 않는다.
  • 왜냐 싱글톤 빈에서 스프링 컨테이너에 프로토타입 빈을 더이상 요청하지 않기 때문.
  • 해결하기 위해서는 싱글톤 빈에서 applicationContext를 주입 받고 매번 요청하면 해결 가능..
  • 이처럼 의존관계를 직접 찾는 것을 dependency loockup (DL)이라 함.
  • 흠.. 근데 applicationContext를 주입받아서 사용하는거는 좀...

 

이 문제는 해결하기 위해서는 딱 DL기능 만  제공하는 기능이 필요

 

1. ObjectFactory, objectProvider


  • ObjectFactory : getObject만 제공함.
  • ObjectProvider : ObjectFactory를 상속받음, 편의기능 추가됨.
  • ObjectProvider : objectProvider에 요청 할 때 스프링 컨테이너에 요청해서 해당 타입 빈 가져옴.
  • 즉 ObjectProvider에 요청하면 직접 applicationContext에 요청하는 것 과 동일한 효과
  • 요청할 때 마다 새로운 인스턴스 반환해줌.
  • Test
    - logic을 실행 할 때 마다
    - ObjectProvider에서 prototypeBean을 받음
    - count 증가
    @Test
    void singletonClientPrototype(){
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(ClientBean.class, PrototypeBean.class);

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

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

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

        @Autowired
        private ObjectProvider<PrototypeBean> prototypeBeanProvider;

//        @Autowired
//        public ClientBean(PrototypeBean prototypeBean) {
//            this.prototypeBean = prototypeBean;
//        }
        
        public int logic(){
            PrototypeBean prototypeBean = prototypeBeanProvider.getObject();
            prototypeBean.addCount();
            int count = prototypeBean.getCount();
            return count;
        }
    }
PrototypeBean.inithello.core.scope.SingletonWithPrototypeTest1$PrototypeBean@41e68d87
PrototypeBean.inithello.core.scope.SingletonWithPrototypeTest1$PrototypeBean@6d3c5255
  • 정리 
    ObejctProvider는 스프링컨테이너 통해 DL을 간단하게 하도록 도와주는 기능임.
    프로토타입 전용 아님 ㅋㅋ
    ObjectFactory대비 편의기능 제공함, 별도 라이브러리 필요 없지만, 스프링에 의존적임!

2. JSR-330 Provider


  • javax.inject.Provider라는 JSR-330 자바 표준 사용
  • javax.inject:javax.inject:1 라이브러리를 gradle에 추가해주자.
    implementation'javax.inject:javax.inject:1'​
  • Provider
    get 메서드만 제공한다.
  • 사용방법은 ObjectProvider와 유사하다.
    @Autowired
    private Provider<PrototypeBean> prototypeBeanProvider;
    
    public int logic(){
      PrototypeBean prototypeBean = prototypeBeanProvider.get();
      prototypeBean.addCount();
      int count = prototypeBean.getCount();
      return count;
    }​
    실행 경과 매 번 새로운 인스턴스가 생성되었다. 
  • PrototypeBean.inithello.core.scope.SingletonWithPrototypeTest1$PrototypeBean@d62fe5b PrototypeBean.inithello.core.scope.SingletonWithPrototypeTest1$PrototypeBean@737a135b​
  • 특징 
    - get 메서드 하나로 단단
    - 별도 라이브러리
    - 자바 표준 사용 --> 다른 컨테이너에서 사용 쌉가능

 

3. 정리


  • 언제 프로토타입 빈 사용?? 매번 사용할 때 마다 의존관계 주입이 완료된 새로운 객체가 필요한 경우
  • ObjectProvider, JSR303 Provider는 프로토타입 뿐 만 아니라 DL필요한 경우 사용
  • 그럼 둘 중에 뭘 사용해야 하나?
    - 스프링 말고 다른 컨테이너 에서 사용해야 한다? --> JSR303 Provider
    - 그럴 일 없다? --> ObjectProvider
      자바 표준이랑, 스프링 제공 기능이 겹칠 때도 있음..

4.GitHub : 210801 Provider


 

 

GitHub - bsh6463/SpringCoreFunction

Contribute to bsh6463/SpringCoreFunction development by creating an account on GitHub.

github.com

 

Comments