Notice
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
01-09 18:44
Today
Total
관리 메뉴

그날그날 공부기록

스프링의 @Configuration과 싱글톤 본문

Spring 공부

스프링의 @Configuration과 싱글톤

given_dragon 2022. 7. 21. 14:46
@Configuration
public class AppConfig {

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

    @Bean
    public MemberRepository memberRepository() {
        System.out.println("call AppConfig.memberRepository");
        return new MemoryMemberRepository();
    }
    @Bean
    public DiscountPolicy discountPolicy(){
        return new FixDiscountPolicy();
    }
}

위 설정 파일에서 memberRepository()는 여러 번 호출된다.

그렇다면 new로 MemoryMemberRepository가 여러 번 만들어질 텐데 싱글톤이 어떻게 유지될까?

실제로 여러번 호출되는지 확인하기 위해 프린트 코드를 넣었다.

 

우선 같은 인스턴스인지 확인해 보기 위해서 테스트 코드를 작성해보았다.

public class ConfigSingletonTest {

    @Test
    void configTest(){
        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("memberService -> memberRepository = " + memberRepository1);
        System.out.println("orderService -> memberRepository = " + memberRepository2);
        System.out.println("memberRepository -> memberRepository = " + memberRepository);

        Assertions.assertThat(memberRepository1).isSameAs(memberRepository2);
    }
}

스프링 컨테이너에서 memberRepository를 사용하는 빈을 꺼내고 각 빈에서 사용되는 memberRepository 인스턴스를 반환해 출력해보았다.(구현체에 getMemberRepository라는 메서드를 만들어두었다.)

모두 같은 인스턴스라는걸 확인할 수 있다.

 

콘솔에서 출력되는 내용도 확인해보았다.

AppConfig에는 memberRepository()는 3번 호출되는데 정작 실제로 호출되는 횟수는 한 번인걸 확인할 수 있다.


스프링이 어떻게 싱글톤을 유지하는지 확인하기 위해 AppConfig 빈을 출력해보았다.

순수한 AppConfig 빈이 아닌 EnhancerBySpringCGLIB라는 것이 출력된다.

설정 파일에 @Configuration이 붙으면 스프링은 싱글톤을 보장하기 위해 CGLIB을 통해 바이트 코드를 조작한다.
→ @Bean이 붙은 메서드마다 스프링 빈이 존재하면 해당 스프링 빈 반환 && 존재하지 않는다면 스프링 빈에 등록하고 반환

 

그렇게 AppConfig를 상속하는 새로운 클래스를 만들고, 그것을 Bean에 등록한다.

(해당 클래스는 AppConfig의 자식 클래스이므로 AppConfig타입으로 조회가 가능하다.)


만약 설정 파일에 @Configuration이 붙지 않으면 CGLIB을 통해 코드를 조작하지 않고 순수한 AppConfig가 빈으로 등록된다.

당연하지만 싱글톤은 보장되지 않는다!

싱글톤이 보장되지 않아 memberRepository가 3번 호출된다.

@Autowired를 통해 해결할 수 있긴 하지만 꼭 필요한 경우가 아니라면 그냥 설정파일에는 @Configuration을 쓰자.

 


출처 - 김영한님 스프링 강의!

https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8

 

스프링 핵심 원리 - 기본편 - 인프런 | 강의

스프링 입문자가 예제를 만들어가면서 스프링의 핵심 원리를 이해하고, 스프링 기본기를 확실히 다질 수 있습니다., - 강의 소개 | 인프런...

www.inflearn.com

 

'Spring 공부' 카테고리의 다른 글

스프링의 의존관계 주입 방법  (0) 2022.07.26
@ComponentScan & @Autowired에 대하여  (0) 2022.07.22
싱글톤 방식의 주의점  (0) 2022.07.21
싱글톤 컨테이너  (0) 2022.07.19
BeanDefinition  (0) 2022.07.18
Comments