✔︎ 스프링 컨테이너 생성
컨테이너에 등록된 빈 조회
hello.core.beanfind.ApplicationContextInfoTest.java
- 27줄에 ac.getBeandDefinition(beanDefinitionName) → bean에 대한 metadate 정보
- spring이 내부에서 사용하는 빈은 getRole()로 구분 가능
- ROLE_APPLICATION : 일반적으로 사용자가 정의한 빈
- ROLE_INFRASTRUCTURE : 스프링이 내부에서 사용하는 빈
★ soutm → system.out.println 단축키
✔︎ 스프링 빈 조회 - 기본
ApplicationContextBasicFindTest.java
- assertThat같은 경우는 검증하는것
- asserThat의 경우 Assertions.assertThat에서 option+enter해서 on-demand로 Assertions를 없앰 (줄임말)
- 항상 test를 할때는 실패 test도 있어야해서 빈 이름으로 조회X test도 진행함
- 마지막 빈 이름으로 조회X부분에서는 () -> 뒷부분의 로직을 실행했을때 앞의 예외가 던져져야 함
✔︎ 스프링 빈 조회 - 동일한 타입이 둘 이상부터 시작
ApplicationContextSameBeanFindTest.java
package hello.core.beanfind;
import hello.core.member.MemberRepository;
import hello.core.member.MemoryMemberRepository;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Map;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;
public class ApplicationContextSameBeanFindTest {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SameBeanConfig.class);
@Test
@DisplayName("타입으로 조회시 같은 타입이 둘 이상 있으면, 중복 오류가 발생한다")
void findBeanByTypeDuplicate(){
// MemberRepository bean = ac.getBean(MemberRepository.class);
assertThrows(NoUniqueBeanDefinitionException.class, () -> ac.getBean(MemberRepository.class));
}
@Test
@DisplayName("타입으로 조회시 같은 타입이 둘 이상 있으면, 빈 이름을 지정하면 된다")
void findBeanByName(){
MemberRepository memberRepository = ac.getBean("memberRepository1", MemberRepository.class);
assertThat(memberRepository).isInstanceOf(MemberRepository.class);
}
@Test
@DisplayName("특정 타입을 모두 조회하기")
void findAllBeanByType(){
Map<String, MemberRepository> beansOfType = ac.getBeansOfType(MemberRepository.class);
for(String key : beansOfType.keySet()){
System.out.println("key = " + key + " value = " + beansOfType.get(key));
}
System.out.println("beansOfType = " + beansOfType);
assertThat(beansOfType.size()).isEqualTo(2);
}
@Configuration
static class SameBeanConfig{
@Bean
public MemberRepository memberRepository1(){
return new MemoryMemberRepository();
}
@Bean
public MemberRepository memberRepository2(){
return new MemoryMemberRepository();
}
}
}
- getBean에서 option+command+v → 앞부분 자동완성
★ command + shifht + enter → 자동 세미콜론 생성
✔︎ 스프링 빈 조회 - 상속 관계
ApplicationContextExtendsFindTest.java
package hello.core.beanfind;
import hello.core.discount.DiscountPolicy;
import hello.core.discount.FixDiscountPolicy;
import hello.core.discount.RateDiscountPolicy;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Map;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;
public class ApplicationContextExtendsFindTest {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(TestConfig.class);
@Test
@DisplayName("부모 타입으로 조회시, 자식이 둘 이상 있으면, 중복 오류가 발생한다")
void findBeanByParentTypeDuplicate(){
// DiscountPolicy bean = ac.getBean(DiscountPolicy.class);
assertThrows(NoUniqueBeanDefinitionException.class, () -> ac.getBean(DiscountPolicy.class));
}
@Test
@DisplayName("부모 타입으로 조회시, 자식이 둘 이상 있으면, 빈 이름을 지정하면 된다")
void findBeanByParentTypeBeanName(){
DiscountPolicy rateDiscountPolicy = ac.getBean("rateDiscountPolicy", DiscountPolicy.class);
assertThat(rateDiscountPolicy).isInstanceOf(RateDiscountPolicy.class);
}
@Test
@DisplayName("특정 하위 타입으로 조회")
void findBeanBySubType(){
RateDiscountPolicy bean = ac.getBean(RateDiscountPolicy.class);
assertThat(bean).isInstanceOf(RateDiscountPolicy.class);
}
@Test
@DisplayName("부모 타입으로 모두 조회하기")
void findAllBeanByParentType(){
Map<String, DiscountPolicy> beansOfType = ac.getBeansOfType(DiscountPolicy.class);
// beansOfType의 사이즈가 2개면 성공
assertThat(beansOfType.size()).isEqualTo(2);
for (String key : beansOfType.keySet()){
System.out.println("key = " + key + " value = " + beansOfType.get(key));
}
}
@Test
@DisplayName("부모 타입으로 모두 조회하기 - Object")
void findAllBeanByObjectType(){
Map<String, Object> beansOfType = ac.getBeansOfType(Object.class);
for(String key : beansOfType.keySet()){
System.out.println("key = " + key + " value = " + beansOfType.get(key));
}
}
@Configuration
static class TestConfig{
@Bean
public DiscountPolicy rateDiscountPolicy(){
return new RateDiscountPolicy();
}
@Bean
public DiscountPolicy fixDiscountPolicy(){
return new FixDiscountPolicy();
}
}
}
✔︎ BeanFactory와 ApplicationContext
- BeanFactory
- 스프링 컨테이너의 최상위 인터페이스
- 스프링 빈을 관리하고 조회하는 역할 담당
- getBean() 제공
- 대부분의 기능을 제공
- ApplicationContext
- BeanFactory 기능을 모두 상속받아서 제공
- BeanFactory + 부가기능
➜ 결론
- ApplicationContext는 빈 관리기능 + 편리한 부가기능 제공
- BeanFactory나 ApplicationContext를 스프링 컨테이너라고 부름
✔︎ 다양한 설정 형식 지원 - 자바 코드, XML
XmlAppContext.java
- GenericXml ← xml이라는 문서를 설정정보로 사용
src/main/resources/appConfig.xml
- new-xml configuration file-spring config 에서 파일 생성
- <bean></bean> 빈 등록
✔︎ 스프링 빈 설정 메타 정보 - BeanDefinition
- BeanDefinition
- 역할과 구현을 개념적으로 나눈 것
- xml이나 자바 코드를 읽어서 BeanDefinition을 만들 수 있음
- 스프링 컨테이너가 자바코드인지 xml인지에 상관없이 BeanDefinition만 알면 됨
- 스프링 컨테이너는 이 메타정보를 기반으로 스프링 빈을 생성
BeanDefinitionTest.java
'개발 > spring' 카테고리의 다른 글
[스프링] 싱글톤 컨테이너 (0) | 2024.04.26 |
---|---|
[스프링] 스프링 핵심 원리 - 기본편 2 (0) | 2023.11.27 |
[스프링] 스프링 핵심 원리 - 기본편 1 (0) | 2023.11.27 |
[스프링] start (0) | 2023.11.06 |