[스프링 기본] 싱글톤(2)

마코레·2022년 5월 18일
0

백엔드개발

목록 보기
15/18
post-thumbnail

🤗 인프런 [스프링 핵심원리-기본편]을 듣고 기록하는 글입니다

@Configuration과 싱글톤


전까지 했던 코드가 싱글톤이라고 했는데, 진짜로 싱글톤이 맞는지 의심이 됨

  • @Bean memberService를 호출하면 → new MemoryMemberRepository 생성
  • @Bean orderSerivce를 호출하면 → new MemoryMemberRepository 생성

각각 다른 MemoryMemberRepository가 생성돼서 싱글톤이 깨지는거처럼 보임. 과연 Spring Container는 이걸 어떻게 싱글톤으로 관리하는가?

//MemberServiceImpl
//테스트 코드
    public MemberRepository getMemberRepository() {
        return memberRepository;
    }
//OrderServiceImpl
//테스트 코드
    public MemberRepository getMemberRepository() {
        return memberRepository;
    }
//테스트코드
//분명 자바코드로 내가 직접 만든거라 싱글톤 깨질 줄 알았는데, 객체가 같음
@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("memberRepository1 = " + memberRepository1);
        System.out.println("memberRepository2 = " + memberRepository2);
        System.out.println("memberRepository = " + memberRepository);
    }

  • 테스트코드 결과, 그냥 memberRepository하고, Service 생성할때 꺼내지는 memberRepository하고 셋다 같은 bean임(bean id가 똑같음)

이제, appconfig쪽에서 bean 함수 호출때마다 "call AppConfig.memberService"이런식으로 출력문 출력하게끔 코드를 바꾸고,

//appconfig에서 객체가 호출되는 순서를 보기위해 출력문 작성
public class AppConfig {

    //spring container라는 증거
    @Bean
    public MemberService memberService() {
        System.out.println("call AppConfig.memberService");
        return new MemberServiceImpl(memberRepository());
    }
  1. memberService
  2. orderService
  3. memberRepository 를 호출해봤음. test코드로
    그랬더니, 만약 싱글톤이 보장이 안된다면 "call AppConfig.memberRepository"가 총 3번 호출돼야하는데 딱 1번만 출력됨

@Configuration과 바이트코드 조작


  • memberRepository가 딱 한번만 호출된 마법은 어떻게 된건가?
    - appconfig에 @Configuration 달아서 그런거임
  • test에서 appconfig 클래스 명을 출력해보면, 그냥 appConfig라고 나오지 않고, 뒤에 xxxCGLIB가 붙으면서 상당히 복잡한 이름이 나옴
  • 내가 만든 클래스가 아니라 스프링이 CGLIB라는 바이트코드 조작 라이브러리를 이용해서 AppConfig를 상속받은 임의의 다른 클래스를 만들고, 그것들 bean으로 등록한것
  • 이 임의의 클래스가 singleton을 보장해주는것.

CGLIB 동작방식

  • @Bean이 붙은 메서드마다 이미 스프링 빈이 존재하면 존재하는 bean 반환
  • 없는경우 생성해서 스프링빈으로 등록하고 이를 반환하는 코드가 동적으로 만들어짐
  • 이런식으로 싱글톤이 보장되는것

@Configuration을 안붙인다면?

  • 사실 저거 안붙여도 @Bean때문에 빈등록이됨
  • 그치만 문제가 발생
  • 싱글톤이 깨지고, 아까 test코드 돌리면 3번 생성돼서 호출됨.
  • 왜냐면 진짜로 spring container에 빈등록된게 아니고 순수 자바코드로 내가 생성한거나 다름없기 때문임
profile
새싹 백엔드 개발자

0개의 댓글