작성
·
57
·
수정됨
0
[질문 템플릿]
1. 강의 내용과 관련된 질문인가요? (예)
2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)
3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)
[질문 내용]
여기에 질문 내용을 남겨주세요.
안녕하세요, @Bean을 통해 컨테이너에 빈을 등록할 때 생성되는 인스턴스에 대한 궁금점이 있습니다.
강의 코드에서는 다음과 같이 AppConfig.java
에서 MemberRepository를 new MemoryMemberRepository()
를 통해 매번 생성하여 반환하고, 이를 memberService()
그리고 orderService()
에서 생성하여 호출하고 있습니다.
@Bean
public MemberRepository memberRepository() {
return new MemoryMemberRepository();
}
@Bean
public MemberService memberService() {
return new MemberServiceImpl(memberRepository());
}
@Bean
public OrderService orderService() {
return new OrderServiceImpl(memberRepository(), discountPolicy());
}
여기서 제가 궁금한 점은 memberRepository()
를 통해 매번 새롭게 생성되는 MemoryMemberRepository를 호출하는 것으로 예상하고 실제 메모리 참조를 확인해보니 모두 동일한 값을 가지는 것을 확인했습니다.
아래는 코드 중 일부입니다.
MemberService, OrderService에 다음을 추가
MemberRepository getMemberRepository();
아래는 위 메소드를 각 Impl에서 구현한 코드입니다.
@Override
public MemberRepository getMemberRepository() {
return this.memberRepository;
}
public static void main(String[] args)의 일부
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
MemberService memberService = applicationContext.getBean("memberService", MemberService.class);
OrderService orderService = applicationContext.getBean("orderService", OrderService.class);
MemberRepository repo = applicationContext.getBean("memberRepository", MemoryMemberRepository.class);
System.out.println("member Service Repository = " + memberService.getMemberRepository());
System.out.println("order Service Repository = " + orderService.getMemberRepository());
System.out.println("member repository bean = " + repo);
실행 결과
member Service Repository = hello.core.member.MemoryMemberRepository@5552768b
order Service Repository = hello.core.member.MemoryMemberRepository@5552768b
member repository bean = hello.core.member.MemoryMemberRepository@5552768b
이에 대해 다음과 같은 두 가지 질문이 있습니다.
memberRepository
는 new를 통해 매번 새롭게 생성하지만 같은 주소를 가지는 이유가 스프링 컨테이너 내부에 빈으로 등록되었기 때문인지 궁금합니다.
만약 인스턴스마다 다른 값을 가지고 있어야 하는 경우가 있다면, 필요에 따라 @Bean
을 통해 생성 해야 하는건지 궁금합니다.
감사합니다.
제가 강의 도중 궁금증이 생겨 확인, 질문했었는데 내용 후반부에 싱글톤과 관련된 설명이 있군요... 머쓱..
답변 1
1
안녕하세요, 인프런 AI 인턴입니다. 말하는 감자님.
스프링에서 @Bean
을 사용하여 빈을 등록할 때, 스프링 컨테이너는 해당 빈을 싱글톤으로 관리합니다. 이것이 바로 memberRepository
메소드가 여러 번 호출되어 new MemoryMemberRepository()
가 호출되는 것처럼 보이지만, 실제로는 같은 인스턴스를 반환하게 되는 이유입니다.
싱글톤 컨테이너 원리: 스프링 컨테이너는 기본적으로 싱글톤 범위로 빈을 관리합니다. 따라서 같은 타입의 빈은 처음 한 번만 생성되고, 이후에는 매번 같은 인스턴스를 컨테이너로부터 반환합니다. 이로 인해 memberRepository()
메소드에서 객체를 여러 번 생성하는 것처럼 보이지만, 실제로는 스프링 컨테이너가 동일한 인스턴스를 반환하게 됩니다. 이런 방식으로 객체의 메모리 사용을 절약하고, 일관성을 유지할 수 있습니다.
다른 인스턴스가 필요할 때: 만약 각 요청마다 새로운 인스턴스를 생성해야 한다면, 스프링의 프록시 기반 스코프 방식이나, @Scope("prototype")
을 사용하여 빈을 정의할 수 있습니다. @Scope("prototype")
을 사용하면 매번 빈 요청 시 새로운 인스턴스를 반환합니다. 단, 이 경우는 컨테이너가 빈의 라이프사이클을 관리하지 않으므로 직접 생명주기 관리를 해주어야 합니다.
다음 문서와 질문에서 더 많은 정보를 참고하실 수 있습니다:
- 스프링 싱글톤 레지스터 원리
- 같은 Bean 인스턴스 재사용에 대해 궁금합니다
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.