@Configuration과 싱글톤
그런데 이상한 점이 있다. 코드를 보자
public class AppConfig {
//@Bean memberService -> new MemoryMemberRepository()
//@Bean orderSErvice -> 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'가 생성되면서 싱글톤이 깨지는 것 처럼 보인다. 스프링 컨테이너는 이 문제를 어떻게 해결할까?
직접 테스트 해보자.
public class AppConfig {
//@Bean memberService -> new MemoryMemberRepository()
//@Bean orderSErvice -> new MemoryMemberRepository()
//call AppConfig.memberService
//call AppConfig.memberRepository
//call AppConfig.memberRepository
//call AppConfig.orderService
//call AppConfig.memberRepository
//call AppConfig.memberService
//call AppConfig.memberRepository
//call AppConfig.orderService
@Bean
public MemberService memberService() {
System.out.println("call AppConfig.memberService");
return new MemberServiceImpl(memberRepository());
}
@Bean
public OrderService orderService() {
System.out.println("call AppConfig.orderService");
return new OrderServiceImpl(
memberRepository(),
discountPolicy());
}
@Bean
public MemberRepository memberRepository() {
System.out.println("call AppConfig.memberRepository");
return new MemoryMemberRepository();
}
@Bean
public DiscountPolicy discountPolicy() {
return new RateDiscountPolicy();
}
}
public class ConfigurationSingletonTest {
@Test
void configurationTest() {
AnnotationConfigApplicationContext 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 -> memberRepository = " + memberRepository1);
System.out.println("orderService -> memberRepository = " + memberRepository2);
System.out.println("memberRepository = " + memberRepository);
Assertions.assertThat(memberService.getMemberRepository()).isEqualTo(memberRepository);
Assertions.assertThat(orderService.getMemberRepository()).isEqualTo(memberRepository);
}
}
'Study > Spring' 카테고리의 다른 글
[Spring 핵심 원리 - 기본편] @Configuration과 바이트코드 조작의 마법 (0) | 2023.02.19 |
---|---|
[Spring 핵심 원리 - 기본편] 싱글톤 방식의 주의점 (0) | 2023.02.19 |
[Spring 핵심 원리 - 기본편] 싱글톤 컨테이너 (0) | 2023.02.19 |
[Spring 핵심 원리 - 기본편] 싱글톤 패턴 (0) | 2023.02.19 |
[Spring 핵심 원리 - 기본편] 웹 애플리케이션과 싱글톤 (0) | 2023.02.19 |