Spring

[Spring] @Configuration과 싱글톤, 바이트 코드 조작

뚜코맨 2024. 1. 6. 22:30

 

싱글톤 패턴을 학습 한 후 소스코드를 보던 중에

 

이 코드를 한번 자세히 보자.

 

현재 memberService(), orderService()memberRepository()를 호출하고 있다.

 

자바 코드에 의해서, memberRepository()가 호출되면서 return new MemoryRepository()를 실행하게 된다.

 

그러면 여기서 잠깐,

싱글톤은 하나의 객체만 생성되어야하고, 공유를 해야하는 것인데.. 자바 코드로만 보면 객체 생성을 2번하고 있는 것 같다...

 

과연 내가 호출할 때마다 memberRepository()가 계속 생성 되는 것이 사실인지 테스트 코드를 통해 알아보자.

 

각각 memberServiceImpl(), orderServiceImpl()에 테스트를 위해 생성한 memberRepository를 반환 시켜보았다.

 

 

실행결과는 놀랍게도 예상과는 다르게 같은 값이라는 거다...

 

정말 내가 생각한대로 호출이 이루어지는지 soutm을 통해서 찍어보았다.

 

 

이렇게 했을 때 콘솔이 어떻게 나올지 생각해보자.

 

(순서에 상관없이)

call AppConfig.memberService
call AppConfig.memberRepository
call AppConfig.orderService

call AppConfig.memberRepository

...

 

이런식으로 memberRepository가 여러번 나오게 될 것 같다..

 

실제로는 과연 그럴까?

 

그렇지 않다..

이쯤되면 스프링이 무언가 싱글톤 패턴을 위해서 어떻게든 막아두는 것 같다..

 

어떻게 스프링은 내가 자바코드로 여러번을 호출했는데도 불구하고 이렇게 싱글톤패턴을 유지할 수 있는걸까?

 

바로 스프링은 바이트 코드 조작 라이브러리를 통해 싱글톤 패턴을 유지할 수 있게 된 것이다.

 

내가 만든 AppConfig() 스프링 빈을 조회를 해보자

 

정상적인 클래스라면, class hello.core.AppConfig 이렇게 출력되지 않겠는가..

 

근데 예상과는 다르게 클래스명에 xxxCGLIB가 붙으면서 복잡하게 바뀐 것을 볼 수 있다. 이것은 내가 만든 클래스가 아니라 스프링이 CGLIB라는 바이트코드 조작 라이브러리를 사용해서 AppConfig 클래스를 상속받은 임의의 다른 클래스를 만들고, 그 다른 클래스를 스프링 빈으로 등록한 것이다!

 

 

내가 만든 AppConfig가 아니라 스프링이 만든 임의의 다른 클래스가 싱글톤이 보장되도록 해준다.

 

정리

  1. @Bean이 붙은 메서드마다 이미 스프링컨테이너에 스프링 빈이 존재하면 존재하는 빈을 반환하고, 없으면 생성해서 빈으로 등록하고 반환하는 코드가 동적으로 만들어진다.
  2. 덕분에 싱글톤이 보장되는 것이다.