@ComponentScan을 통해 등록된 객체(빈)들은 오른쪽 그림처럼 의존관계가 주입되는데 이때 @AutoWired를 쓸 수도 있고,
생성자 주입을 쓸 수도 있다.
스프링은 기본적으로 싱글톤 패턴을 지원하는데, 싱글톤 패턴은 클래스의 객체가 딱 1개만 생성되는 것을 보장하는 디자인 패턴이다.
한 클래스의 객체a가 서로다른 두 클래스의 객체에 의존관계가 됐을때, 이 두객체안에 있는 객체a는 같은주소를 가진 동일한 객체일까?
@Component @RequiredArgsConstructor public class UserService {
private final ItemRepository itemRepository; public ItemRepository getItemRepository() { return itemRepository; } }
@Service @Getter @RequiredArgsConstructor public class ItemService {
private final ItemRepository itemRepository; public ItemRepository getItemRepository() { return itemRepository; } }
이 두개의 서비스에서 itemRepository객체를 필드로 가지고 있다.
@SpringBootTest public class InstanceTest { @Autowired private UserService userService; @Autowired private ItemService itemService; @Test @DisplayName("userService의 itemRepository와 itemService의 itemRepository는 같나") public void test1() { assertThat(userService.getItemRepository()).isEqualTo(itemService.getItemRepository()); } }
테스트를 통해 확인한 결과 두 객체는 동일한 객체이다.
스프링이 없는 순수 자바로 테스트를 해보자. 위의 코드와 아래코드는 다르게 표현된 같은 코드이다.단 아래는 스프링을 안썼기에 직접 대입을 해준 것이다.
public class InstanceTest {
private UserService userService = new UserService(new ItemRepository()); private ItemService itemService = new ItemService(new ItemRepository()); @Test @DisplayName("userService의 itemRepository와 itemService의 itemRepository는 같나") public void test1() { assertThat(userService.getItemRepository()).isEqualTo(itemService.getItemRepository()); } }
이런 에러가 나타난다. 두 객체는 다른 객체이다.
스프링이 객체들을 스프링빈으로 등록하여 관리할때는 이런 결과가 나오지 않았다.
스프링은 스프링빈의 객체가 딱 1개만 생성되는 것을 보장하기 위해 CGLIB라는 기술을 사용한다.
class AppConfigurationTest {
@Test void configurationDeep() { ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfiguration.class); AppConfiguration bean = ac.getBean(AppConfiguration.class); System.out.println("bean.getClass() = " + bean.getClass()); } }
이 테스트를 실행시켜 보면
bean.getClass() = class springselfStudy.study.configuration.AppConfiguration$$SpringCGLIB$$0
이런 결과가 나오는 것을 볼 수 있다. 우리가 작성한 Appconfiguration에 $$SpringCGLIB$$0이 붙었다. 이것은 스프링이 CGLIB라는 바이트 코드 조작 라이브러리를 사용해서 내가 만든 클래스를 상속받은 어떤 클래스를 만들고, 그 클래스를 스프링 빈으로 등록한 것이다. 이 클래스가 스프링빈의 객체가 딱 1개만 생성되는 것을 보장해준다.
댓글 영역