위 코드를 보면 new 키워드로 객체를 반환하고 있다.
그렇다면 orderService()를 2번 호출하면 OrderService와 OrderRepository가 2번씩 생성되지 않을까?
결론부터 말하면 아니다.
orderService()와 orderRepository()가 호출될 때 위 처럼 메시지가 출력되도록 했다. 어떻게 나올까?
2번씩 호출되는 것이 아니라 1번 씩 호출된다. 즉 싱글톤이 보장되었다.
@Configuration 어노테이션
@Configuration 클래스 내에 정의된 메소드들 중 @Bean 어노테이션이 붙은 메소드들은 스프링 컨테이너에 의해 빈(bean)으로 등록되고
이러한 빈들은 스프링 컨테이너에 의해 관리된다.
또한 @Configuration 어노테이션이 붙은 클래스는 스프링 컨테이너에 의해 특별한 방식으로 처리된다.
이 특별한 방식은 xxx@CGLIB라는 객체는 스프링이 xxx 클래스를 상속받는 프록시 객체를 만들고, 이 프록시 객체를 Bean으로 등록한 것이다.
그리고 이 프록시 객체에는 이미 스프링 컨테이너에 Bean이 존재하면 기존 Bean을 반환하고, 없으면 스프링 컨테이너에 Bean을 등록하는 코드가 동적으로 만들어진다.
@Configuration 어노테이션을 사용할 때와 사용하지 않을 때 비교
꼭 수동 bean 등록시에 해당 클래스에 @Configuration 어노테이션을 붙여야할까?
아래 코드를 통해 @Configuration 어노테이션를 사용하지 않을 때와 사용할 때를 비교해보자.
@Test
void useSingleton() {
// given
ApplicationContext ac = new AnnotationConfigApplicationContext(OrderConfig.class);
OrderService orderService1 = ac.getBean("orderService", OrderService.class);
OrderService orderService2 = ac.getBean("orderService", OrderService.class);
OrderConfig bean = ac.getBean(OrderConfig.class);
System.out.println("저장된 Bean 이름 : " + bean.getClass());
// when && then
assertThat(orderService1).isSameAs(orderService2);
}
@Configuration 어노테이션 사용X
@Configuration을 사용하지 않았을 경우 orderService와 orderRepository가 2번씩 호출될 것을 생각했는데
orderService는 한 번만 호출되었다. 왜 1번만 호출된걸까?
위 코드에서 OrderService는 스프링 컨테이너를 통해 직접 요청하고 있어 싱글톤이 보장된 것이다.
하지만 orderService()메서드 내부에서 orderRepository() 메서드를 호출하면 new 키워드로 OrderRepository의 새 인스턴스가 매번 생성기 때문에
orderRepository는 2번 호출된 것이다.
즉, 정리하자면
빈을 정의하는 클래스에 @Configuration 어노테이션이 없더라도 스프링 컨테이너에 직접 요청한 객체는 싱글톤이 보장된다.
하지만 설정 클래스 내부에서 빈 생성 메서드를 직접 호출할 경우 싱글톤이 보장되지 않는다.
설정 클래스를 사용할 때는 @Configuration 어노테이션을 붙여서 스프링이 클래스를 특별하게 처리하도록 하는 것이 좋다.
@Configuration 어노테이션 사용 O
OrderConfig 뒤에 CGLIB가 붙은 프록시 객체가 등록된 것을 볼 수 있다.
그리고 orderService() 내부에서 호출된 orderRepository도 2번 호출되는 것이 아닌 CGLIB 프록시 객체를 통해 한 번만 호출되었다.
'◼ Spring' 카테고리의 다른 글
[Spring] Bean이 2개 이상일 때 특정 Bean 선택 방법 (다형성 의존성 주입) (1) | 2024.04.16 |
---|---|
[Spring] 스프링 싱글톤 방식의 주의점 (1) | 2024.04.15 |
[Spring] 스프링의 싱글톤 패턴과 싱글톤 컨테이너에 대해 알아보자. (0) | 2024.04.15 |
의존성 주입(DI)이란? (OCP와 DIP를 지키기 위한 방법) (1) | 2024.04.12 |
[Spring AOP] 모든 페이지의 공통 헤더 영역에 공통 데이터 Model에 담아 전달 (0) | 2023.09.21 |