ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 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

     

    [출처 - 스프링 핵심 원리 - 기본편]

    댓글

Designed by Tistory.