[Spring] 김영한 스프링 기본 정리 #4 - 스프링 컨테이너와 스프링 빈
1. 스프링 컨테이너와 스프링 빈 정리
2. 스프링 컨테이너 생성
스프링 컨테이너는 애플리케이션의 설정 정보를 바탕으로 스프링 빈을 관리하고 의존관계를 주입하는 역할을 한다.
// 스프링 컨테이너 생성
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
ApplicationContext
는 스프링 컨테이너의 인터페이스이다.- 자바 설정 클래스를 기반으로 스프링 컨테이너가 생성된다.
3. 스프링 컨테이너 생성 과정
- 스프링 컨테이너 생성
- 설정 정보를 제공하여 컨테이너를 생성한다.
- 스프링 빈 등록
- 설정 클래스 정보를 바탕으로 스프링 빈을 등록한다.
- 빈 이름은 기본적으로 메서드 이름을 사용하지만, 직접 지정할 수도 있다.
- 스프링 빈 의존관계 설정 - 준비
- 빈들 간의 의존관계를 설정한다.
- 스프링 빈 의존관계 설정 - 완료
- 의존관계가 모두 주입되며 준비가 완료된다.
4. 컨테이너에 등록된 모든 빈 조회
스프링 컨테이너에 등록된 빈을 출력하여 확인할 수 있다.
String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
for (String name : beanDefinitionNames) {
Object bean = applicationContext.getBean(name);
System.out.println("name=" + name + " object=" + bean);
}
getBeanDefinitionNames()
: 모든 빈의 이름을 반환한다.getBean(name)
: 빈 이름으로 객체를 조회한다.
5. 애플리케이션 빈만 출력하기
스프링 내부에서 사용하는 빈을 제외하고, 직접 등록한 애플리케이션 빈만 출력할 수 있다.
for (String name : beanDefinitionNames) {
BeanDefinition beanDefinition = applicationContext.getBeanDefinition(name);
if (beanDefinition.getRole() == BeanDefinition.ROLE_APPLICATION) {
Object bean = applicationContext.getBean(name);
System.out.println("name=" + name + " object=" + bean);
}
}
6. 스프링 빈 조회 - 기본
스프링 컨테이너에서 빈을 조회하는 기본 방법은 다음과 같다:
// 빈 이름과 타입으로 조회
MemberService memberService = applicationContext.getBean("memberService", MemberService.class);
- 이름과 타입을 함께 지정하면 정확히 원하는 빈을 조회할 수 있다.
- 타입만으로도 조회 가능하지만, 중복된 타입이 있을 경우 오류가 발생할 수 있다.
예제 코드
@Test
@DisplayName("빈 이름으로 조회")
void findBeanByName() {
MemberService memberService = ac.getBean("memberService", MemberService.class);
assertThat(memberService).isInstanceOf(MemberServiceImpl.class);
}
7. 스프링 빈 조회 - 동일한 타입이 둘 이상
- 같은 타입의 스프링 빈이 둘 이상이면 오류가 발생한다.
- 이때는 빈 이름을 명시하거나, 모든 빈을 조회하는 방법을 사용한다.
Map<String, MemberRepository> beansOfType = applicationContext.getBeansOfType(MemberRepository.class);
for (String key : beansOfType.keySet()) {
System.out.println("key = " + key + " value = " + beansOfType.get(key));
}
8. 스프링 빈 조회 - 상속 관계
부모 타입으로 조회하면 자식 타입도 함께 조회된다.
@Test
@DisplayName("부모 타입으로 조회시, 자식이 둘 이상 있으면, 빈 이름을 지정")
void findBeanByParentType() {
DiscountPolicy discountPolicy = ac.getBean("rateDiscountPolicy", DiscountPolicy.class);
assertThat(discountPolicy).isInstanceOf(RateDiscountPolicy.class);
}
9. BeanFactory와 ApplicationContext
BeanFactory
: 스프링 컨테이너의 최상위 인터페이스로, 빈 관리와 조회 기능을 제공한다.ApplicationContext
:BeanFactory
의 기능을 모두 상속받고, 추가적인 부가 기능을 제공한다.- 메시지소스를 활용한 국제화 기능
- 환경 변수 및 애플리케이션 이벤트 관리
- 편리한 리소스 조회 기능 등
10. 다양한 설정 형식 지원
스프링 컨테이너는 다양한 설정 형식을 지원한다:
- 자바 코드 기반 설정:
AnnotationConfigApplicationContext
- XML 기반 설정:
GenericXmlApplicationContext
예제:
ApplicationContext ac = new GenericXmlApplicationContext("appConfig.xml");
MemberService memberService = ac.getBean("memberService", MemberService.class);
assertThat(memberService).isInstanceOf(MemberService.class);
XML 설정 예시 (appConfig.xml
):
<beans xmlns="http://www.springframework.org/schema/beans">
<bean id="memberService" class="hello.core.member.MemberServiceImpl">
<constructor-arg name="memberRepository" ref="memberRepository"/>
</bean>
<bean id="memberRepository" class="hello.core.member.MemoryMemberRepository"/>
<bean id="orderService" class="hello.core.order.OrderServiceImpl">
<constructor-arg name="memberRepository" ref="memberRepository"/>
<constructor-arg name="discountPolicy" ref="discountPolicy"/>
</bean>
<bean id="discountPolicy" class="hello.core.discount.RateDiscountPolicy"/>
</beans>
11. BeanDefinition
스프링은 다양한 설정 형식을 BeanDefinition
으로 추상화하여 사용한다.
- 자바 코드나 XML 설정을 읽어
BeanDefinition
을 생성한다.
예제:
@Test
@DisplayName("빈 설정 메타정보 확인")
void findApplicationBean() {
String[] beanDefinitionNames = ac.getBeanDefinitionNames();
for (String name : beanDefinitionNames) {
BeanDefinition beanDefinition = ac.getBeanDefinition(name);
if (beanDefinition.getRole() == BeanDefinition.ROLE_APPLICATION) {
System.out.println("beanDefinitionName=" + name + " beanDefinition=" + beanDefinition);
}
}
}
12. 정리
- 스프링 컨테이너는 설정 정보를 바탕으로 스프링 빈을 관리하고 의존관계를 설정한다.
ApplicationContext
는 빈 관리 기능과 함께 다양한 부가 기능을 제공한다.- 다양한 설정 형식을
BeanDefinition
으로 추상화하여 유연하게 지원한다.
댓글남기기