인프런 커뮤니티 질문&답변

hw h님의 프로필 이미지
hw h

작성한 질문수

스프링 핵심 원리 - 기본편

프로토타입 스코프 - 싱글톤 빈과 함께 사용시 문제점

프로토타입 빈 관련 질문있습니다.

작성

·

535

·

수정됨

0

    @Test
    void singletonClientUsePrototype() {

        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(PrototypeBean.class);

        PrototypeBean bean = ac.getBean(PrototypeBean.class);

        String[] beanDefinitionNames = ac.getBeanDefinitionNames();

        for (String beanDefinitionName : beanDefinitionNames) {
            BeanDefinition beanDefinition = ac.getBeanDefinition(beanDefinitionName);
            if(beanDefinition.getRole() == BeanDefinition.ROLE_APPLICATION)
                System.out.println("beanDefinitionName = " + beanDefinitionName);
        }
    }

@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 " + this);
        }

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

 

프로토타입 빈을 ac.getBean 을 통해 요청하고 그 이후에 스프링 컨테이너를 조회했을때 프로토타입 빈이 존재하는지 확인해볼려고 위와 같이 코드를 작성하였습니다.

그 결과로

4.png

이와 같이 프로토타입 빈이 스프링 컨테이너에 있는걸 확인했습니다. 여기서 궁금한 점이

 

1. 스프링 컨테이너가 프로토타입 빈을 관리하지 않는 시점이란게 ac.getBean(PrototypBean.class) 을 실행한 바로 이후가 맞을까요?

 

2. ac.getBean(PrototypBean.class) 를 통해 빈을 반환하였고 그 뒤로는 스프링 컨테이너에서 해당 빈을 관리하지 않는다면 왜 프로토타입 빈이 여전히 스프링 컨테이너에서 조회가 되는지 궁금합니다. 제가 생각해본 바로는 ac.getBean(PrototypBean.class) 이후에는 스프링 컨테이너에 해당 프로토타입빈이 존재하지 않지만, 해당 프로토타입 빈의 beanDefintion은 여전히 존재하여 위와 같은 결과가 나왔다라고 생각이 들었는데 이게 맞을까요?

 

3. 해당 PrototypeBean 클래스에는 @PostConstruct 어노테이션을 통해 프로토타입 스프링빈이 의존관계 주입을 마칠떄 beanDefinitionName = ... 메세지가 뜨도록 설정하였습니다. 그런데 위 예제에서는

AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(PrototypeBean.class);

코드로 한번

PrototypeBean bean = ac.getBean(PrototypeBean.class);

코드로 두번 프로토타입 빈을 요청하였으므로 해당 메세지가 2번이 떠야하는게 아닌가요? 왜 한번만 발생하는지 궁금합니다. 이것도 제가 생각해본 바로는 스프링컨테이너를 생성하는 시점에 싱글톤타입과 다르게 프로토타입은 beanDefinition 만 생성이되고 스프링빈이 생성되지는 않기 때문에 위와 같은 결과가 나왔다라고 생각이 들었는데 이게 맞는 내용인지 궁금합니다.

 

답변 2

2

안녕하세요. hw h님, 공식 서포터즈 David입니다.

이와 같이 프로토타입 빈이 스프링 컨테이너에 있는걸 확인했습니다.

엄밀히 따지면, 컨테이너에 (싱글톤) 빈이 존재하는 것과 BeanDenifition이 있는 건 다른 의미입니다.

BeanDefinition은 빈을 생성할 수 있는 정보입니다. 컨테이너는 이런 정보를 들고 있습니다.

다만, 프로토타입의 경우 컨테이너가 가지고 있는 정보를 바탕으로 빈이 생성된 뒤 바로 반환되며 생성된 빈이 컨테이너에 따로 등록되진 않습니다. 그러므로 컨테이너로부터 관리 받지 않는다고 말하는 것입니다.

이 부분을 구분하시면 고민하시는 부분들이 명확해질 것 같습니다.

이외 질문하신 것들은 모두 생각하신 게 맞습니다.

감사합니다.

0

안녕하세요, 인프런 AI 인턴이에요.

코드를 보면 @Scope(“prototype”) 어노테이션과 함께 정의된 PrototypeBean 클래스가 있습니다. 이 클래스는 프로토타입 스코프로 설정되어 있습니다.
여기서 만약 ac.getBean(PrototypeBean.class) 코드를 통해 프로토타입 빈을 요청하게 되면, 매번 새로운 인스턴스가 생성됩니다.
그런데 ac.getBeanDefinitionNames()을 통해 프로토타입 빈을 확인하고자 하신다면, 이미 컨테이너에 존재하는 빈의 인스턴스를 가져오게 됩니다.
이는 싱글톤 빈에 대한 조회 방법이기 때문에, 원하는 결과를 얻을 수 없을 것입니다.

프로토타입 빈은 매번 요청할 때마다 새로운 객체를 반환하기 때문에, 프로토타입 빈이 컨테이너에 존재하는지 여부를 직접 확인하기는 어렵습니다.
프로토타입 빈이 정상적으로 생성되었는지 확인하고 싶다면, 위와 같은 방법대신 프로토타입 빈의 생명 주기 메서드를 사용하여 출력문을 작성해볼 수 있습니다.
예를 들어 init() 메서드와 destroy() 메서드에서 출력문을 추가하여 프로토타입 빈의 생성과 소멸을 확인해보세요.

이렇게 하시면 프로토타입 빈이 정상적으로 생성되는지 확인할 수 있을 것입니다.
더 자세한 내용은 스프링 프레임워크의 스코프에 대해 학습하시면 도움이 될 것입니다.

더 궁금한 사항이 있으면 언제든지 물어보세요. 좋은 하루 되세요!

hw h님의 프로필 이미지
hw h

작성한 질문수

질문하기