@Configuration 을 알아보기 위해서 이 코드를 살펴보자,
시나리오
1. @Bean memberService 를 호출하면 ➡️ MemoryMemberRepository() 를 한번 호출한다.
2. @Bean orderService 를 호출하면 ➡️ MemoryMemberRepository() , discountPolicy() 를 호출한다.
이렇게 하면 결과적으로 각각 다른 2개의 MemoryMemberRepository() 가 두 번 호출 되니까 싱글톤이 깨지는게 아닐까요?? 스프링 컨테이너가 싱글톤을 보장해준다고 했는데 과연 그럴까?? 직접 테스트 해보자
✅ 테스트 방법
1. MemoryMemberRepository 를 불러오는 MemberServiceImpl 에서
테스트 용도로 MemberServiceImpl, OrderServiceImpl 둘 다 각각 생성자로 들어오는 memberRepository 의 값을 확인하는 getMemberRepository 메서드를 만들었다.
2. 각각의 memberRepository 를 테스트 코드를 통해 확인해보자.
밑에는 테스트코드이고
밑에는 테스트 코드의 결과이다.
결과는 세개의 memberRepository가 같은 것을 확인할 수 있다. 분명 세번의 다른 memberRepository의 인스턴스가 호출될 것 같았지만 모두 같은 인스턴스가 공유되어 사용되고 있음을 확인할 수 있었다. 어떻게 된 일일까? 혹시 두 번 호출이 안되는 것일까? 다음 실험을 통해 알아보자.
이렇게 호출 되는 부분마다 찍어보면서 확인해보았다.
찍어본 세 개의 메서드 각각 한번씩 호출 되었는 것을 볼 수 있다. 이 비밀이 어디에 있을까?? ➡️ @Configuration 을 적용한 AppConfig 에 있다.
시나리오
1. AppConfig 스프링 빈을 조회해서 클래스 정보를 출력해보자.
순수한 클래스라면 다음과 같이 출력되어야 한다.
class hello.core.AppConfig
그런데 예상과는 다르게 클래스 명에 xxxCGLIB가 붙으면서 상당히 복잡해진 것을 볼 수 있다. 이것은 내가 만든 클래스가 아니라 스프링이 CGLIB 이라는 바이트코드 조작 라이브러리를 사용해서 AppConfig 클래스를 상속받은 임의의 다른 클래스를 만들고, 그 다른 클래스를 스프링 빈으로 등록한 것이다.
그 임의의 다른 클래스가 바로 싱글톤이 보장되도록 해준다. 아마도 다음과 같이 바이트 코드를 조작해서 작성되어 있을 것이다. (실제로는 CGLIB의 내부 기술은 매우 복잡하다.)
- @Bean이 붙은 메서드마다 이미 스프링 빈이 존재하면 존재하는 빈을 반환하고, 스프링 빈이 없으면 생성해서 스프링 빈으로 등록하고 반환하는 코드가 동적으로 만들어진다.
- 덕분에 싱글톤이 보장되는 것이다.
만약 @Configuration 을 적용하지 않고, @Bean 만 적용하면 어떻게 될까?
@Configuration 을 붙이면 바이트코드를 조작하는 CGLIB 기술을 사용해서 싱글톤을 보장하지만, 만약 @Bean만 적용하면 어떻게 될까?
@Configuration 을 주석처리 하고 @Bean 만 적용해보고 밑에 테스트 코드를 다시 돌려보았다.
결과로 이렇게 나왔다.
CGLIB 기술을 사용 하지 않은 순수한 AppConfig 가 나왔다. 그리고
memberRepository가 여러번 호출되는 것을 확인할 수 있듯이 순수한 자바 코드가 나오면서 싱글톤이 깨진다!!
정리
- @Bean만 사용해도 스프링 빈으로 등록되지만, 싱글톤을 보장하지 않는다.
- memberRepository() 처럼 의존관계 주입이 필요해서 메서드를 직접 호출할 때 싱글톤을 보장하지 않는다.
- 크게 고민할 것이 없다. 스프링 설정 정보는 항상 @Configuration 을 사용하자.
'프레임워크 > Spring' 카테고리의 다른 글
[Spring] 다양한 의존관계 주입 방법 (0) | 2022.06.21 |
---|---|
[Spring] 컴포넌트 스캔 - @ComponentScan (0) | 2022.06.20 |
[Spring] 싱글톤 패턴 주의점 (0) | 2022.06.18 |
[Spring] 싱글톤 컨테이너 (0) | 2022.06.18 |
[Spring] 스프링 컨테이너 생성 과정 (0) | 2022.06.15 |