- 스프링 컨테이너는 싱글톤 레지스트리.
- 스프링이 자바 코드까지 어떻게 하기는 어렵다!
- 그래서 스프링이 클래스의 바이트코드를 조작하는 라이브러리를 사용한다.
- 이전에 @configuration과 싱글톤에서 MemberRepository가 3번 호출이 아닌 1번만 호출되었던 이유를 알아보자.
TEST
@Test
void configurationDeep() throws Exception {
//given
ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
AppConfig bean = ac.getBean(AppConfig.class);
//when
System.out.println("bean.getClass() = " + bean.getClass());// bean.getClass() = class hello.core.AppConfig$$SpringCGLIB$$0
// 순수한 클래스인 경우 : class hello.core.AppConfig
// xxxCGLIB : 내가 만든 클래스가 아니라 스프링이 CGLIB라는 바이트코드 조작 라이브러리를 사용해서 AppConfig 클래스를 상속받은 임의의 다른 클래스를 만들고, 그 다른 클래스를 스프링 빈으로 등록. 임의의 다른 클래스가 싱글톤이 보장되도록해준다.
}
-
순수한 클래스인 경우 : class hello.core.AppConfig
-
xxxCGLIB : 내가 만든 클래스가 아니라 스프링이 CGLIB라는 바이트코드 조작 라이브러리를 사용해서 AppConfig 클래스를 상속받은 임의의 다른 클래스를 만들고, 그 다른 클래스를 스프링 빈으로 등록. 임의의 다른 클래스가 싱글톤이 보장되도록해준다.
-
아마도 AppConfig@CGLIB가 이미 스프링 빈이 존재하면 빈을 반환하고, 스프링 빈이 없으면 생성해서 스프링 빈으로 등록하고 반환하는 코드가 동적으로 만들어진다.
-
즉, @bean이 붙은 메서드마다 스프링 빈이 존재하면, 해당 빈을 반환하고 없다면 해당 메서드를 호출해서 스프링 빈으로 등록하고 반환한다.
@configuration을 주석처리한 뒤, TEST 코드를 재실행해 보았다.
정리
@configuration과 바이트코드 조작의 마법
TEST
순수한 클래스인 경우 : class hello.core.AppConfig
xxxCGLIB : 내가 만든 클래스가 아니라 스프링이 CGLIB라는 바이트코드 조작 라이브러리를 사용해서 AppConfig 클래스를 상속받은 임의의 다른 클래스를 만들고, 그 다른 클래스를 스프링 빈으로 등록. 임의의 다른 클래스가 싱글톤이 보장되도록해준다.
아마도 AppConfig@CGLIB가 이미 스프링 빈이 존재하면 빈을 반환하고, 스프링 빈이 없으면 생성해서 스프링 빈으로 등록하고 반환하는 코드가 동적으로 만들어진다.
즉, @bean이 붙은 메서드마다 스프링 빈이 존재하면, 해당 빈을 반환하고 없다면 해당 메서드를 호출해서 스프링 빈으로 등록하고 반환한다.
@configuration없이 @bean만 사용한다면?
@configuration을 주석처리한 뒤, TEST 코드를 재실행해 보았다.
configurationDeep 재실행
configurationTest 재실행
위 3개의 인스턴스 객체 주소가 다 다르다. → 싱글톤 보장 X
정리