@Configuration// 애플리케이션의 설정 정보publicclassAppConfig{
@Bean// 스프링 컨테이너에 등록된다.public MemberRepository memberRepository(){ // 객체 생성을 메소드 처리
System.out.println("call AppConfig.memberRepository");
returnnew MemoryMemberRepository(); // 새로운 구현체를 주입 하고 싶다면 new 객체를 수정하면 된다.
}
@Beanpublic DiscountPolicy discountPolicy(){ // 객체 생성을 메소드 처리//return new FixDiscountPolicy(); // 새로운 구현체를 주입 하고 싶다면 new 객체를 수정하면 된다.returnnew RateDiscountPolicy();
}
@Beanpublic MemberService memberService(){
System.out.println("call AppConfig.memberService");
returnnew MemberServiceImpl(memberRepository());
}
@Beanpublic OrderService orderService(){
System.out.println("call AppConfig.orderService");
returnnew OrderServiceImpl(memberRepository(), discountPolicy());
}
}
로직상으로는 call AppConfig.memberRepository 3번 호출 되어야 하지만 , 1번만 호출된다.
memberService빈을 만드는 코드를 보면 memberRepository()를 호출한다
이 메서드를 호출하면 new MemoryMemberRepository()를 호출한다.
orderService빈을 만드는 코드도 동일하게 memberRepository()를 호출한다.
이 메서드를 호출하면 new MemoryMemberRepository()를 호출한다.
결과적으로 각각 다른 2개의 MemoryMemberRepository()가 생성되면서 싱글톤이 깨지는 것 처럼 보인다.
스프링 컨테이너는 이 문제를 어떻게 해결할까?
@Configuration은 싱글톤을 위해 존재한다.
// MemberServiceImpl , OrderServiceImpl 테스트 용도로 // 각각 주입 된 memberRepository를 반환 하는 메소드 추가public MemberRepository getMemberRepository(){
return memberRepository;
}
@Configuration 과 싱글톤
AppConfig
@Configuration // 애플리케이션의 설정 정보 public class AppConfig { @Bean // 스프링 컨테이너에 등록된다. public MemberRepository memberRepository() { // 객체 생성을 메소드 처리 System.out.println("call AppConfig.memberRepository"); return new MemoryMemberRepository(); // 새로운 구현체를 주입 하고 싶다면 new 객체를 수정하면 된다. } @Bean public DiscountPolicy discountPolicy(){ // 객체 생성을 메소드 처리 //return new FixDiscountPolicy(); // 새로운 구현체를 주입 하고 싶다면 new 객체를 수정하면 된다. return new RateDiscountPolicy(); } @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()); } }
결과적으로 각각 다른 2개의 MemoryMemberRepository()가 생성되면서 싱글톤이 깨지는 것 처럼 보인다.
스프링 컨테이너는 이 문제를 어떻게 해결할까?
// MemberServiceImpl , OrderServiceImpl 테스트 용도로 // 각각 주입 된 memberRepository를 반환 하는 메소드 추가 public MemberRepository getMemberRepository(){ return memberRepository; }
ConfigurationSingletonTest
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 memberRepository1 = memberService.getMemberRepository(); MemberRepository memberRepository2 = orderService.getMemberRepository(); MemberRepository memberRepository3 = ac.getBean("memberRepository", MemberRepository.class); System.out.println("memberService -> MemberRepository = " + memberRepository1); System.out.println("orderService -> MemberRepository = " + memberRepository2); System.out.println("memberRepository = " + memberRepository3); // memberService -> MemberRepository = hello.core.member.MemoryMemberRepository@37091312 // orderService -> MemberRepository = hello.core.member.MemoryMemberRepository@37091312 // memberRepository = hello.core.member.MemoryMemberRepository@37091312 Assertions.assertThat(memberService.getMemberRepository()).isSameAs(memberRepository3); Assertions.assertThat(orderService.getMemberRepository()).isSameAs(memberRepository3); } }
@Configuration과 바이트코드 조작의 마법
AppConfig 스프링 빈을 조회해서 클래스 정보를 출력
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class); AppConfig bean = ac.getBean(AppConfig.class); System.out.println("appConfig = " + bean.getClass()); //appConfig = class hello.core.AppConfig$$EnhancerBySpringCGLIB$$ba528fbb
@Configuration을 적용하지 않고 , @Bean만 적용하면 어떻게 될까?
스프링 핵심 원리 - 기본편 - 인프런
스프링 입문자가 예제를 만들어가면서 스프링의 핵심 원리를 이해하고, 스프링 기본기를 확실히 다질 수 있습니다. 초급 프레임워크 및 라이브러리 웹 개발 서버 개발 Back-End Spring 객체지향 온
www.inflearn.com
'스프링 핵심 원리 > 싱글톤 컨테이너' 카테고리의 다른 글