이번 글을 이해하기 위해선 스프링 빈(Bean)의 대한 기초적인 지식이 필요합니다.
모르고계시면 빈(Bean)에 대해서 검색하시거나 이걸 참고하시면 될거같습니다.
먼저 둘이 어떤 공통점이 있는지 말씀드리겠습니다.
1. 빈(Bean)을 생성하고 관리하는 기능을 제공.
Spring Framework에서 빈(Bean)은 애플리케이션에서 사용되는 객체를 말합니다.빈(Bean)을 생성하고 관리하는 기능은 객체를 생성하고 필요한 시점에 사용 가능한 상태로 만들어주며, 빈(Bean)의 종속성을 해결해주는 등의 역할을 수행합니다.
2. 빈(Bean)의 라이프사이클(생명주기)을 관리하는 기능을 제공.
빈(Bean)의 라이프사이클을 관리하는 기능을 제공합니다. 빈(Bean)의 라이프사이클은 생성, 초기화, 소멸 등의 단계를 말하며, 이러한 단계에서 빈(Bean)을 초기화하거나 소멸시키는 작업을 수행합니다.
3. 빈(Bean) 스코프를 관리.
BeanFactory와 ApplicationContext는 빈(Bean)의 스코프를 관리합니다. 스코프는 빈(Bean)의 생명주기와 관련되며, 빈(Bean)이 생성되고 소멸되는 시점을 결정합니다. 스프링 프레임워크에서는 다양한 스코프를 지원합니다.
4. 의존성 주입(Dependency Injection)을 지원.
BeanFactory와 ApplicationContext는 의존성 주입(Dependency Injection)을 지원합니다. 의존성 주입은 객체 간의 의존성을 외부에서 설정해주는 것을 말합니다. 이를 통해 빈(Bean)들 간의 의존성을 해결하고 객체 간의 결합도를 낮출 수 있습니다.
둘은 많은 차이점이 존재하지만 개인적으로 더 중요한 차이점만 말씀드리겠습니다.
xml파일을 이용해 빈 객체를 로드하는 방식
// BeanFactory를 사용하는 코드
BeanFactory factory = new XmlBeanFactory(new ClassPathResource("application-context.xml"));
MyBean bean = factory.getBean(MyBean.class); // MyBean 객체는 실제로 사용되는 시점에 생성.
// ApplicationContext를 사용하는 코드
ApplicationContext context = new ClassPathXmlApplicationContext("application-context.xml");
MyBean bean = context.getBean(MyBean.class); // MyBean 객체는 컨테이너 초기화 시점에 생성.
BeanFactory를 사용하는 경우에는 getBean() 메소드가 호출될 때마다 빈 객체가 생성되며, ApplicationContext를 사용하는 경우에는 컨테이너가 초기화될 때 모든 빈 객체가 생성됩니다.
자바 클래스 파일로 빈 객체를 로드하는 방식
TestService클래스
public class TestService {
private static boolean isLoaded;
public TestService() {
isLoaded = true;
}
public static boolean isIsLoaded() {
return isLoaded;
}
}
@Test
void beanFactoryTest() { // Lazy Loading방식
GenericApplicationContext context = new GenericApplicationContext(); //스프링 컨테이너 생성
context.refresh();
context.registerBean("testService", TestService.class);
String[] beanDefinitionNames = context.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
System.out.println("beanDefinitionName = " + beanDefinitionName);
BeanDefinition beanDefinition = context.getBeanDefinition(beanDefinitionName);
System.out.println("bb = " + beanDefinition);
}
Assertions.assertFalse(TestService.isIsLoaded());
TestService testService = (TestService) context.getBean("testService"); // 최초로 빈 요청 시점에 빈 생성
Assertions.assertTrue(TestService.isIsLoaded());
}
// ------------------------------------------------------------------------------
void AppicationContextTest() {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(config.class); // 스프링 컨테이너 생성
String[] beanDefinitionNames = ac.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
BeanDefinition beanDefinition = ac.getBeanDefinition(beanDefinitionName);
System.out.println(beanDefinition);
}
System.out.println();
TestService testService = ac.getBean("testService", TestService.class);
Assertions.assertTrue(TestService.isIsLoaded());
}
기본적으로 스프링 프레임워크의 빈은 싱글톤(Singleton) 스코프로 생성
빈의 로딩 방식 중 Lazy loading방식은 빈 객체를 처음 사용할 때까지 생성을 미루는 방식으로 최초 요청 시 한번만 초기화되고 이후 요청에서는 기존에 생성된 객체를 반환
eager loading방식은 애플리케이션 시작 시점에 모두 생성되는 방식으로 스프링 애플리케이션이 생성될 때 자동으로 컨테이너를 생성하는데 그 시점에 등록된 빈들을 생성함으로써 빈 요청이 있을 때 초기화 작업없이 바로 사용 가능