@Configuration 과 Singleton
Singleton이 무엇인지 Spring Container를 통해 이를 유지하는 것을 확인해보았다.
AppConfig를 다시 보자
스프링이 초기화되어 스프링 컨테이너에 Bean들이 등록될 때를 생각해보자.
- memberService() -> memberRepository() 호출
- 이는 new MemoryMemberRepository()를 호출
- orderService() -> memberRepository()호출
- new MemoryMemberRepository()호출
응?? 이렇게되면 MemoryMemberRepository가 2개가 생성되어 싱글톤이 깨지는 것이 아닌가??
직접 테스트를 해보자!
먼저, MemberServiceImpl 과 OrderServiceImlp 클래스에 각각 memberRepository의 값을 반환하는 메소드를 만들어둔다.
그 후 테스트 코드를 작성하여 직접 참조값을 출력해보려한다.
위와같이 구현체타입으로 조회하는 것은 좋지 않은 방법이지만, 단순 테스트이므로 위와 같이 작성했다.
2개의 객체가 생성되어 서로 다를 것이라 생각했던 것과 달리 둘 다 같은 객체 인스턴스를 참조하고 있는 것을 확인할 수 있다. 즉, 모두 같은 인스턴스가 공유되어 사용 중
AppConfig에 호출 로그를 남겨보자
다음과 같이 호출될 때마다 출력문을 수행하게 하여 직접 로그를 찍어보자.
앞에서 생각한대로라면
- memberService를 통해 memberRepository가 호출
- memberRepository를 Bean에 등록하기위해 호출
- orderService를 통해 memberRepository가 호출
따라서 call AppConfig.memberRepository가 총 3번 출력되지 않을까???
우리의 생각과는 전혀 다르게 딱 1번씩만 호출되는 것을 확인할 수 있다.
- memberService
- memberRepository
- orderService
@Configuration과 바이트코드 조작의 마법
스프링 컨테이너는 싱글톤 레지스트리다. 따라서 스프링 빈이 싱글톤이 되도록 보장해주어야함. 위에서 우리가 살펴본 자바 코드를 보면 분명 3번 호출되어야 하는 것이 맞다.
하지만 스프링은 클래스의 바이트코드를 조작하는 라이브러리를 사용하여 싱글톤을 보장해준다.
이는 @Configuration을 적용한 AppConfig에 그 비밀이 있다.
먼저 AppConfig의 클래스명을 출력해보자.(AppConfig도 빈으로 등록됨)
class hello.core.AppConfig가 아닌 그 뒤에 ~~CGLIB가 붙으면서 굉장히 복잡해진 것을 볼 수 있다.
이것은 내가 만든 클래스가 아니라 스프링이 CGLIB라는 바이트코드 조작 라이브러리를 사용해서 AppConfig 클래스를 상속받은 임의의 다른 클래스를 만들고, 그 다른 클래스를 스프링 빈으로 등록한 것이다.
그 임의의 다른 클래스가 바로 싱글톤이 보장되도록 해준다.
- @Bean이 붙은 메서드마다 이미 스프링 빈이 존재하면 존재하는 빈을 반환하고, 없으면 생성해서 스프링 빈으로 등록하고 반환하는 코드가 동적으로 만들어진다.
- 이 덕분에 싱글톤이 보장되는 것이다.
AppConfig@CGLIB는 AppConfig의 자식 타입이므로, AppConfig 타입으로 조회 가능
그럼, @Configuration을 적용하지 않고, @Bean만 적용하면?
@Configuration을 주석처리하고 앞서 만든 테스트 코드를 실행시켜보겠다.
우리가 초기에 생각했던대로 호출이 되는 것을 확인할 수 있다.
AppConfig 빈의 클래스 명또한 순수한 클래스 명인 class hello.core.AppConfig이고
memberRepository가 3번 호출되었다.
심지어 이것은 orderService와 memberSerivce는 각각 다른 MemoryMemberRepository 인스턴스를 가지고 있다. 또한 스프링 컨테이너에서 관리도 되지 않는다.
즉, @Configuration을 통하여 스프링이 싱글톤을 보장해주고 있었던 것이다.
@Bean만 사용해도 스프링 빈으로 등록되지만, 싱글톤을 보장하지 않고 컨테이너에서 관리도 되지 않는다.
크게 고민할 필요없이 스프링 설정 정보는 항상 @Configuration을 붙이자!
반응형
'Spring > Spring Core' 카테고리의 다른 글
탐색 위치와 기본 스캔 대상 (0) | 2021.03.13 |
---|---|
컴포넌트 스캔과 의존관계 자동 주입 (0) | 2021.03.13 |
Singleton 방식의 주의점 (0) | 2021.03.12 |
Singleton Pattern & Singleton Container (0) | 2021.03.11 |
Web Application & Singleton (0) | 2021.03.11 |