사실 @Configuration은 싱글톤 때문에 있는 것이다.
다음 AppConfig 코드를 보자. (이상한 것이 있다)
public class AppConfig {
// @Bean memberService --> new MemoryMemberRepository()
// @Bean orderService --> new MemoryMemberRepository()
@Bean
public MemberService memberService() {
return new MemberServiceImpl(new memberRepository());
}
@Bean
public MemberRepository memberRepository() {
return new MemoryMemberRepository();
}
@Bean
public OrderService orderService() {
return new OrderServiceImpl(
memberRepository(),
discountPolicy());
}
...
}
- memberService 빈을 만드는 코드를 보면 memberRepository()를 호출한다.
- 이 메서드를 호출하면 new MemoryMemberRepository()를 호출한다.
- orderService 빈을 만드는 코드도 동일하게 memberRepository()를 호출한다.
- 이 메서드를 호출하면 new MemoryMemberRepository()를 호출한다.
결과적으로 각각 다른 2개의 MemoryMemberRepository가 생성되면서 싱글톤이 꺠지는 것처럼 보인다.
스프링 컨테이너는 이 문제를 어떻게 해결할까 ?
직접 테스트 해보자.
`검증 용도의 코드 추가`
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 -> memberRepository = " + memberRepository1);
System.out.println("orderService -> memberRepository = " + memberRepository2);
System.out.println("memberRepository = " + memberRepository);
assertThat(memberService.getMemberRepository()).isSameAs(memberRepository);
assertThat(orderService.getMemberRepository()).isSameAs(memberRepository);
}
}
- 확인해보면 memberRepository 인스턴스는 모두 같은 인스턴스가 공유되어 사용된다
- AppConfig의 자바 코드를 보면 분명히 각각 2번 new MemoryMemberRepository를 호출해서 다른 인스턴스가 생성되어야 하는데?
- 어떻게 된 일일까 ? 혹시 두번 호출이 안되는 것일까 ?
스프링 컨테이너가 @Bean을 호출해서 스프링 빈을 생성한다. 그래서 memberRepository()는 다음과 같이
총 3번이 호출되어야 하는 것 아닐까?
- 1. 스프링 컨테이너가 스프링 빈에 등록하기 위해 @Bean이 붙어있는 memberRepository() 호출
- 2. memberService() 로직에서 memberRepository() 호출
- 3. orderService() 로직에서 memberRepository() 호출
그런데 출력 결과는 모두 1번만 호출된다.
call AppConfig.memberSerivce
call AppConfig.memberRepository
call AppConfig.orderService
'Spring 기본편' 카테고리의 다른 글
[JAVA 8] 스트림(Stream) 이란 ? (0) | 2023.06.14 |
---|---|
빈 스코프란 ? (0) | 2023.04.02 |
웹 애플리케이션과 싱글톤 (0) | 2023.03.20 |
4장-(8). 스프링 빈 설정 메타정보 - BeanDefinition (0) | 2023.03.12 |
4장-(7). 다양한 설정 형식 지원 - 자바코드,XML (0) | 2023.03.12 |