Spring Framework의 핵심인 Spring Container(IoC 컨테이너라고도 함)는 빈을 조회, 등록 등 관리하는 역할을 가지고 있다.
참고로 빈들은 BeanFactory
에 저장되는데, Key-Value 구조의 자료구조인 Map
형태로 저장 됨.
GenericApplicationContext 내부에서 DefaultListableBeanFactory를 멤버로 가짐
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
```
private final Map<String, BeanDefinition> beanDefinitionMap
= new ConcurrentHashMap<>(256);
```
}
그렇다면 스프링 컨테이너가 어떻게 빈을 등록하는지 / 유지하는지 정리해보자.
스프링 컨테이너에 빈을 등록하는 방법으로는 굉장히 많은데 (ApplicationContext
의 구현체는 수많음) 대표적으로 xml로 등록하는 방법과 Java의 어노테이션을 통한 방법이 있다.
우리는 Java의 어노테이션을 이용한 빈 등록 방법을 알아보겠다.
어노테이션을 통한 빈 등록은 모두 ComponentScan
에 의존하게 되고 클래스를 통한 등록 / 메서드를 통한 등록으로 나뉜다.
클래스를 통한 빈 등록은 @Component
- @Target(ElementType.TYPE)
어노테이션을 활용하게 된다. ComponentScan
에서 보이는 Component
말이다.
@Component
public class MyBean {
```
}
이렇게 클래스를 통해 빈을 등록하게 될 경우
myBean
처럼 클래스명을 lower camel case로 바꿔 등록해준다.메서드를 통한 빈 등록은
@Bean
- @Target(ElementType.METHOD,ElementType.ANNOTATION_TYPE)
을 활용하게 된다. 그러나 이 어노테이션은 ComponentScan
의 대상이 되지 못한다. 따라서 @Component내에 생성 메서드를 두고 @Bean을 붙임으로써 간접적으로 빈 등록이 되게 한다.
주의할 점은
@Configuration
클래스 내에 @Bean
메서드를 선언해야 해당 빈이 싱글톤 유지를 받을 수 있다.스프링 컨테이너는 기본적으로 빈들을 싱글톤으로 유지해준다. 어떤 역할인지 눈으로 확인해보자.
@Configuration
public class AppConfig {
@Bean
public MemberInstanceService memberInstanceService() {
MemberInstanceService instanceService = new MemberInstanceService();
System.out.println(instanceService); -------
return instanceService;
}
@Bean
public MemberService memberService() {
MemberInstanceService instanceService = memberInstanceService();
System.out.println(instanceService); --------
return new MemberService(instanceService);
}
}
출력 값
hello.springtx.AppConfig$MemberInstanceService@1190200a
hello.springtx.AppConfig$MemberInstanceService@1190200a
위 소스코드에서 @Configuration
제거
hello.springtx.AppConfig$MemberInstanceService@70e8f8e
hello.springtx.AppConfig$MemberInstanceService@2e4b8173
이렇게 생성 역할을 하는 메서드를 여러번 호출했을 때, 일반적으로는 또 다시 new
연산자에 의해 새 인스턴스가 생기지만
스프링 컨테이너는 해당 빈이 BeanFactory
에 등록돼있다면 (빈 이름으로 구분), 같은 객체의 레퍼런스를 리턴해주는 방식으로 빈을 싱글톤으로 유지하게 된다.