요약
Spring Container에 등록된 Bean에 대한 인스턴스가 실제로 Singleton 패턴이 적용되어 있는지 확인해 보려고 테스트 코드를 작성하였다.
근데, 이상하게도 객체 참조 값이 모두 달라 검증이 되지 않았다.
알고보니 테스트하고 있던 AppConfig에서 해당 Bean을 등록할 때 static으로 선언해서 발생한 문제였다.
해결
해결 방법은 Bean 등록 메서드를 static 하게 선언하지 않으면 된다.
근데 왜 static 하게 Bean 등록 메서드를 사용하면 객체가 Singleton 패턴을 보장받지 못하는걸까?
이유는 다음과 같다.
Spring은 내부적으로 @Bean이 붙은 메서드를 호출하면 Singleton Container에 동일한 Bean이 존재하는지 Proxy를 통해 확인한다.
이때, static Method의 경우 Proxy가 적용되지 않아 Singleton Container에 동일한 Bean이 없다고 판단하고 계속 새로운 객체를 반환하게 되는 것이다.
조금만 더 설명하면 다음과 같다.
static 으로 메서드를 선언하게 되면 Class Loader에 의해 해당 클래스를 메모리에 로드할 때 메모리에 함께 배치된다. 이는, 특정 인스턴스에 속하지 않은 상태를 말한다.
그러나 Spring Container의 경우 인스턴스 레벨에서 라이프사이클 관리, 의존성 주입, 프록시 적용 등을 수행하므로 @Bean 을 통해 Spring Container에 Bean으로 등록해 사용하고 싶다면 non-static Method 로 선언해야 하는 것이다.