인프런 영문 브랜드 로고
인프런 영문 브랜드 로고

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

keoung ko님의 프로필 이미지

작성한 질문수

스프링 핵심 원리 - 기본편

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

의존성 주입 AnnotationConfigApplicationContext에 파라미터로 넘긴 후에는 Autowired를 사용할 필요가없나요?

작성

·

28

0

학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)

[질문 내용]

package hello.core.scope;

import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import lombok.Getter;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import static org.assertj.core.api.Assertions.*;

public class SingletonWithPrototypeTest {

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

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

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

    @Scope("singleton")
    static class ClientBean {

        @Autowired
        private ObjectProvider<PrototypeBean> prototypeBeanProvider;

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

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

        public void addCount() {
            count++;
        }

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

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

강의에서는 AnnotationConfigApplicaionContext를 new로 생성하면서 파라미터로 ClientBean클래스를 넘겨주면서 빈에 등록한 후에 아래 ClientBean 클래스에 Provider를 사용하면서 @Autowired 를 사용 하시더군요
마찬가지로 Provider사용하기 전에 생성자 주입을 할때도 Autowired를 사용하시길래 저도 코드에 Autowired를 추가했는데, 저는 오류가 나더라구요

제가 궁금한점은 @Component어노테이션을 ClientBean클래스에 붙여주면 해결되긴 했는데 강의에선 @Component 어노테이션을 사용하지 않아도 오류가 나지 않길래 저랑 뭐가 다른건지 모르겠어서 질문 합니다. 이미 파라미터로 넘기면서 빈에 등록이 되서 다시 등록하려는거때문에 충돌이나서 그런건가요? 그렇다면 강사님 강의에서 보인 코드는 왜 오류가 나지 않는건가요? 궁금합니다 ㅠㅠ

정리하자면 강사님 강의에선 ClientBean클래스에 @Componenet를 사용하지 않고도 @Autowired를 사용했을때 오류가 나지 않지만 저는 @Autowired만 사용하면 오류가 뜹니다. 어떤 차이가 있는건지 궁금합니다.

답변 2

0

김영한님의 프로필 이미지
김영한
지식공유자

안녕하세요. keoung ko님

도움을 드리고 싶지만 질문 내용만으로는 답변을 드리기 어렵습니다.

@Autowired로 실패하는 경우가 있는 실제 동작하는 전체 프로젝트를ZIP파일로 압축해서 구글 드라이브로 공유해서 링크를 남겨주세요.

구글 드라이브 업로드 방법은 다음을 참고해주세요.

https://inf.run/tLyVZ

 

주의: 업로드시 링크에 있는 권한 문제 꼭 확인해주세요

 

추가로 다음 내용도 코멘트 부탁드립니다.

1. 문제 영역을 실행할 수 있는 방법

2. 문제가 어떻게 나타나는지에 대한 상세한 설명 (오류 화면, 오류 로그 포함)

링크: 공식 서포터즈

링크: 자주하는 질문

감사합니다.

0

인프런 AI 인턴님의 프로필 이미지

안녕하세요, 인프런 AI 인턴입니다.

keoung ko님, 질문 주셔서 감사드립니다. ClientBean 클래스에 @Component 어노테이션을 사용하지 않고도 @Autowired를 사용했을 때 오류가 나지 않는 이유는 강의에서 사용한 ApplicationContext 설정 방식의 차이 때문일 가능성이 큽니다.

AnnotationConfigApplicationContext를 생성할 때, 강의에서 사용한 예제나 설명이 ClientBean을 스프링 컨텍스트에 직접 등록하는 방식이 아닌, 다른 설정 방식이었을 수 있습니다. 이는 주로 XML 설정 파일이나 Java Config에서 @Bean 어노테이션을 사용하여 빈을 등록하는 방법이 있을 수 있습니다.

한편, keoung ko님께서 @Autowired를 사용하실 때 오류가 발생한 것은 ClientBean이 스프링의 관리 대상이 되지 않았기 때문입니다. AnnotationConfigApplicationContext 생성 시, 파라미터로 넘기는 방법은 해당 클래스를 자동으로 @Component 스캔을 통해 등록하지 않기 때문에, @Component를 명시적으로 사용하여 스프링 컨텍스트에 빈으로 등록해 주어야 합니다. 강의에서는 이러한 방식 대신 다른 적절한 빈 등록 방법을 사용했을 가능성이 큽니다.

따라서 강의와 동일한 동작을 원하신다면 강의의 프로젝트 설정 및 @Bean 등의 구체적인 설정 방법을 한 번 더 확인해 보시는 것이 좋습니다.

추가적으로 참고할 수 있는 부분:
- Spring Boot Reference Documentation > Integration Testing

문제가 해결되길 바라며, 추가적인 질문이 있으시면 언제든지 문의 주시기 바랍니다. 감사합니다.