Spring

빈 스코프

스파이더웹 2022. 8. 7. 13:14
728x90
반응형

빈 스코프란?

스프링 빈은 스프링 컨테이너의 시작시 함께 생성되어 컨테이너가 종료될 때 까지 유지된다

그 이유는 스프링 빈이 싱글톤 스코프이기 때문이다

 

스프링의 스코프 종류

1) 싱글톤

  • 기본 스코프이며, 스프링 컨테이너의 시작과 종료까지 유지되는 가장 넓은 범위의 스코프

2) 프로토 타입 

  • 스프링 컨테이너는 프로토타입 빈의 생성과 의존관계 주입까지만 관여하고 더는 관리하지않는 스코프

웹 관련 스코프

1) request 

  • 웹 요청이 들어오고 나갈때 까지 유지되는 스코프

2) session

  • 웹 세션이 생성되고 종료될 때 까지 유지되는 스코프

3) application

  • 웹의 서블리 컨텍스트와 같은 범위로 유지되는 스코프

 

싱글톤 스코프 vs 프로토 타입 스코프

싱글톤 스코프는 싱글톤패턴을 적용하여 항상 같은 인스턴스의 스프링 빈을 반환하지만 프로토타입의 스코프를 조회하면

항상 새로운 인스턴스를 생성해서 반환한다

또한 프로토타입의 스코프는 스프링 컨테이너가 프로토타입 빈을 생성하고 의존관계를 주입,초기화까지만 처리한다는 것이다 클라이언트에 빈을 반환하고, 이후 스프링 컨테이너는 생성된 프로토타입 빈을 관리하지 않는다 초기화 이후 빈을 관리할 책임은 클라이언트에 있으며, @PreDestory와 같은 종료메서드는 호출되지 않는다

 

프로토 타입

public class PrototypeTest {

    @Test
    void prototypeBeanFind(){
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(PrototypeBean.class);

        PrototypeBean bean1 = ac.getBean(PrototypeBean.class);
        PrototypeBean bean2 = ac.getBean(PrototypeBean.class);
        System.out.println("bean1 = " + bean1);
        System.out.println("bean2 = " + bean2);

        Assertions.assertThat(bean1).isNotSameAs(bean2);

        ac.close();
    }

    @Scope("prototype")
    static class PrototypeBean{

        @PostConstruct
        public void init(){
            System.out.println("Singleton 초기화");
        }

        @PreDestroy
        public void destroy(){
            System.out.println("Singleton 종료");
        }
    }
}

다른 객체가 생성되어 초기화도 각각 이루어진것을 볼 수 있으며, 또한 종료메서드는 호출되지않는다 종료메서드를 호출하려면 수동으로 호출해주어야한다

        bean1.destroy();
        bean2.destroy();

 

종료메서드를 수동으로 호출해서 메서드가 호출된것을 볼 수 있다.

 

프로토타입스코프와 싱글톤 빈을 함께 사용했을 경우

스프링 컨테이너에 프로토타입 스코프의 빈을 요청하면 항상 새로운 객체 인스턴스를 생성해서 반환한다.

그러나 싱글톤 빈과 함께 사용할때는 그렇지 않다

예를 들어 아래와 같은코드에서

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

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

            public int logic(){
                prototypeBean.addCount();
                return prototypeBean.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("프로토 타입 초기화 "+ this);
        }

        @PreDestroy
        public void destroy(){
            System.out.println("프로토 타입 종료 ");
        }



    }

ClientBean은 싱글톤이므로 스프링 컨테이너 생성 시점에  함께 생성되고, 의존관계 주입도 발생한다

ClientBean은 의존관계 자동주입을 사용하고 있으며, 주입 시점에 스프링컨테이너에 프로토 타입빈을 반환 한다

그러므로 객체를 생성해서 반환하였으므로, ClientBean을 조회시마다 새로운 프로토타입의 객체가 생성되지는않는다

 

이러한 경우 굳이 프로토타입의 빈을 사용할 이유가 없다.(싱글톤 타입을 사용한것과 동일) 그렇다면 의도했던대로 조회시마다 새로운 빈을 생성하려면 어떻게해야할까?

 

해결방법은

Provider를 사용한다

 @Scope("singleton")
        static class ClientBean {

            @Autowired
            private ObjectProvider<PrototypeBean> prototypeBeanProvider;

            public int logic(){
                PrototypeBean prototypeBean = prototypeBeanProvider.getObject();
                prototypeBean.addCount();
                return prototypeBean.getCount();
            }
        }

1. ObjectProvider 의 getObject() 를 호출하면 내부에서는 스프링 컨테이너를 통해 해당 빈을 찾아서 반환한다

ObjectProvider는 필요한 DL 정도의 기능만 제공한다

 

        @Scope("singleton")
        static class ClientBean {

            @Autowired
            private Provider<PrototypeBean> prototypeBeanProvider;

            public int logic(){
                PrototypeBean prototypeBean = prototypeBeanProvider.get();
                prototypeBean.addCount();
                return prototypeBean.getCount();
            }
        }

2. javax.inject.Provider 라는 JSR-330 자바 표준을 사용하는 방법이다.

방법을 사용하려면 javax.inject:javax.inject:1 라이브러리를 gradle에 추가해야 한다

 

결과는 첫번째 방법과 동일하다

 

웹 스코프

웹 스코프는 웹 환경에서만 동작하며 웹 스코프는 스코프의 종료시점까지 관리한다

 

웹스코프  종류

request : HTTP 요청 하나가 들어오고 나갈때 까지 유지되는 스코프, HTTP 요청별로 빈 인스턴스가 생성되고 관리된다

session : HTTP Session과 동일한 생명주기를 가지는 스코프

application : 서블릿 컨텍스트와 동일한 생명주기를 가지는 스코프

websocket : 웹소켓과 동일한 생명주기를 가지는 스코프

 

 

 

 

 

참조

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/dashboard

 

스프링 핵심 원리 - 기본편 - 인프런 | 강의

스프링 입문자가 예제를 만들어가면서 스프링의 핵심 원리를 이해하고, 스프링 기본기를 확실히 다질 수 있습니다., - 강의 소개 | 인프런...

www.inflearn.com

 

728x90
반응형