-
Spring 기본 15 - @Configuration과 싱글FrameWork/Spring&Spring-boot 2023. 11. 13. 10:16
다음 AppConfig코드르 살펴보자
@Configurable public class AppConfig { //@Bean memberService() -> new MemoryMemberRepository() //@Bean orderService() -> new MemoryMemberRepository() //new MemoryMemberRepository()가 두번 호출 되었는데 //그러면 싱글톤이 깨진거 아닐까? @Bean public MemberService memberService(){ return new MemberServiceImpl(memberRepository()); } @Bean public OrderService orderService(){ return new OrderServiceImpl(memberRepository(), discountPolicy()); } @Bean public MemberRepository memberRepository() { return new MemoryMemberRepository(); } @Bean public DiscountPolicy discountPolicy(){ return new RateDiscountPolicy(); } }
- memberService빈을 만드는 코드를 보면 memberRepository()를 호출한다.
- 해당 메서드를 호출하면 new MemoryMemberRepository()르 호출한다.
- orderService빈을 만드는 코드도 동일하게 memberRepository()를 호출한다.
- 이 메서드를 호출하면 new MemoryMemberRepository()를 호출한다.
결과 적으로 각각 다른 2 개의 MemoryMemberRepository가 생성되면서 싱글톤이 깨지는 것 처럼 보인다. 스프링 컨테이너는 이 문제를 어떻게 해결할까?
@Configurable public class AppConfig { //@Bean memberService() -> new MemoryMemberRepository() //@Bean orderService() -> new MemoryMemberRepository() //new MemoryMemberRepository()가 두번 호출 되었는데 //그러면 싱글톤이 깨진거 아닐까? @Bean public MemberService memberService(){ return new MemberServiceImpl(memberRepository()); } @Bean public OrderService orderService(){ return new OrderServiceImpl(memberRepository(), discountPolicy()); } @Bean public MemberRepository memberRepository() { return new MemoryMemberRepository(); } @Bean public DiscountPolicy discountPolicy(){ return new RateDiscountPolicy(); } }
- 확인해 보면 memberRepository 인스턴스는 모두 같은 인스턴스가 공유되어 사용된다.
- AppConfig의 자바 코드를 보면 분명히 각각 2번 new MemoryMemberRepository 호출로 인해 다른 인스턴스가 생성되어야 하는데?
- 어떻게 된 일일까? 혹시 두 번 호출이 안되는 것일까? 실험을 통해 알아보자
@Configuration public class AppConfig { //@Bean memberService() -> new MemoryMemberRepository() //@Bean orderService() -> new MemoryMemberRepository() //new MemoryMemberRepository()가 두번 호출 되었는데 //그러면 싱글톤이 깨진거 아닐까? @Bean public MemberService memberService(){ System.out.println("call AppConfig.memberService"); return new MemberServiceImpl(memberRepository()); } @Bean public MemberRepository memberRepository() { System.out.println("call AppConfig.memberRepository"); return new MemoryMemberRepository(); } @Bean public OrderService orderService(){ System.out.println("call AppConfig.orderService"); return new OrderServiceImpl(memberRepository(), discountPolicy()); } @Bean public DiscountPolicy discountPolicy(){ return new RateDiscountPolicy(); } }
public class ConfigurationSingletonTest { @Test void configurationTest(){ ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class); MemberServiceImpl memberService = ac.getBean("memberService", MemberServiceImpl.class); OrderServiceImpl orderService = ac.getBean("orderService", OrderServiceImpl.class); MemberRepository memberRepository = ac.getBean("memberRepository", MemberRepository.class); MemberRepository memberRepository1 = memberService.getMemberRepository(); MemberRepository memberRepository2 = orderService.getMemberRepository(); System.out.println("memberService -> memberRepository1 = " + memberRepository1); System.out.println("orderService -> memberRepository2 = " + memberRepository2); System.out.println("memberRepository = " + memberRepository); Assertions.assertEquals(memberRepository,memberRepository1); Assertions.assertEquals(memberRepository,memberRepository2); } }
호출 로그
call AppConfig.memberService
call AppConfig.memberRepository
call AppConfig.orderService[출처 - 스프링 핵심 원리 - 기본편]
'FrameWork > Spring&Spring-boot' 카테고리의 다른 글
Spring 기본 18 - 탐색 위치와 기본 스캔 대상 (0) 2023.11.14 스프링 기본 17 - 컴포넌트 스캔 (0) 2023.11.13 Spring 기본 15 - 싱글톤 방식의 주의점 (0) 2023.11.13 Spring 기본 14 - 싱글톤 컨테이너 (0) 2023.11.12 도메인 주도 개발4 - Entity와 Value1 (0) 2023.11.12 - memberService빈을 만드는 코드를 보면 memberRepository()를 호출한다.