AppConfig의 이상한 점
@Configuration
public class AppConfig {
@Bean
public MemberService memberService() {
return new MemberServiceImpl(memberRepository());
}
@Bean
public OrderService orderService() {
return new OrderServiceImpl(memberRepository(), discountPolicy());
}
@Bean
public MemberRepository memberRepository() {
return new MemoryMemberRepository();
}
...
}
- memberService 빈을 만드는 코드를 보면
memberRepository()
를 호출합니다.- 이 메서드를 호출하면
new MemoryMemberRepository()
를 호출합니다.
- 이 메서드를 호출하면
- orderService 빈을 만드는 코드도 동일하게
memberRepositoy()
를 호출합니다.- 이 메서드를 호출하면
new MemoryMemberRepository()
를 호출합니다.
- 이 메서드를 호출하면
결과적으로 각각 다른 2개의 MemoryMemberRepository
가 생성되면서 싱글톤이 깨지는 것 처럼 보입니다.
테스트 코드
class ConfigurationSingletonTest {
@Test
public 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);
assertThat(memberService.getMemberRepository()).isSameAs(memberRepository);
assertThat(orderService.getMemberRepository()).isSameAs(memberRepository);
}
}
- 확인해보면 MemoryMemberRepository 인스턴스는 모두 같은 인스턴스가 공유되어 사용됩니다.
AppConfig에 호출 로그 남김
@Configuration
public class AppConfig {
@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());
}
...
}
- 출력 결과는 모두 1번만 호출됩니다.
call AppConfig.memberService
call AppConfig.memberRepository
call AppConfig.orderService
참조
'Spring' 카테고리의 다른 글
[스프링 핵심 원리 - 기본편] 컴포넌트 스캔과 의존관계 자동 주입 시작하기 (0) | 2021.09.19 |
---|---|
[스프링 핵심 원리 - 기본편] @Configuration과 바이트코드 조작의 마법 (0) | 2021.09.18 |
[스프링 핵심 원리 - 기본편] 싱글톤 방식의 주의점 (0) | 2021.09.17 |
[스프링 핵심 원리 - 기본편] 싱글톤 컨테이너 (0) | 2021.09.17 |
[스프링 핵심 원리 - 기본편] 싱글톤 패턴 (0) | 2021.09.17 |
댓글