[Spring] @Configuration

노유성·2023년 7월 13일
0
post-thumbnail

Configuration과 싱글톤

@Configuration
public class AppConfig {
    @Bean
    // 생성자를 통해서 주입한다.
    public MemberService memberService() {
        return new MemberServiceImpl(memberRepository());
    }
    @Bean
    public MemberRepository memberRepository() {
        return new MemoryMemberRepository();
    }
    @Bean
    public OrderService orderService()  {
        return new OrderServiceImpl(memberRepository(), discountPolicy());
    }
    @Bean
    public DiscountPolicy discountPolicy() {
        return new RateDiscountPolicy();
    }
}

AppConfig.java 파일을 보면은 수상한 점이 있다. 바로 memberService()에서 memberRepository()를 호출하고 또 orderService()에서도 memberRepository()를 호출한다는 점이다. 이렇게 되면은 memberResporitory()가 총 3번 호출이 되는 거고 결국엔 각각 다른 메모리를 갖게 되는 거 아닐까?

Test

@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);

    System.out.println("orderService.getMemberRepository() = " + orderService.getMemberRepository());
    System.out.println("memberService.getMemberRepository() = " + memberService.getMemberRepository());
    System.out.println("memberRepository = " + memberRepository);

    assertThat(memberService.getMemberRepository()).isEqualTo(orderService.getMemberRepository());
}

스프링 컨테이너에서 빈을 조회해서 각각의 빈의 참조값을 비교해보았다.

결과는 너무나도 당연하게 모든 빈의 참조값이 같았다. 왜그런걸까? 결론만 얘기하면은 스프링은 모든 빈을 싱글톤으로 관리한다. 이것을 가능하게 하는게 @Configuration annotation이다.

그래서 만약에 annotation을 제거하고 test를 하면은

모든 참조값이 변하게 된다.

이런게 어떻게 가능한 걸까? spring이라고 해서 java코드 자체를 바꿀 수 있는게 아닐텐데 말이다.

CGLIB 라이브러리

@Test
void configurationDepp() {
    ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
    AppConfig bean = ac.getBean(AppConfig.class);

    System.out.println("bean = " + bean.getClass());
}

위 코드를 실행하면은 조회된 빈의 class명을 볼 수 있다. 우리는 AppConfig도 bean으로 등록된다는 점을 참고해서 AppConfig의 class를 확인해보았는데

class명이 우리가 기대한 것과는 다르다. 이 이유는 우리가 스프링 컨테이너에 설정정보로 AppConfig를 제공하면은 그것을 그대로 빈으로 만드는게 아니라, AppConfig를 상속받은 새로운 class를 스프링에서 만들어서 빈에 등록한다. 해당 class는 byte코드가 바뀌어서 로직이 더해졌기에 모든 빈을 싱글톤으로 유지하게 한다.

profile
풀스택개발자가되고싶습니다:)

0개의 댓글