🤗 인프런 [스프링 핵심원리-기본편]을 듣고 기록하는 글입니다
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
스프링 컨테이너라고 한다면 사실 BeanFactory, ApplicationContext 두가지고 구분이 가능한데, 일반적으로는 ApplicationContext를 많이쓰고 BeanFactory를 직접 쓰는일은 없음
원래 spring으로 그냥 하면 빈 생성 후, 빈 의존관계 설정이 이루어지는데, 그림처럼 우리가 직접 java코드로 빈을 생성하면 생성과 의존관계 설정이 한꺼번에 됨.
왜냐하면 빈 생성하려고 함수 호출하면 거기안에 의존관계 설정 코드도 들어있기 때문임
조회하는 test 코드
//컨테이너 생성
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
@Test
@DisplayName("모든 빈 출력하기")
void findAllBean() {
//컨테이너를 이용해서 bean이름을 가져오고, 그걸 배열에 담기
String[] beanDefinitionNames = ac.getBeanDefinitionNames();
//배열 속 bean 하나씩 출력하기
for(String beanDefinitionName : beanDefinitionNames) {
Object bean = ac.getBean(beanDefinitionName);
System.out.println("name = " + beanDefinitionName + " object= " + bean);
}
}
-스프링 내부 bean만 보는법
- BeanDefinition.ROLE_INFRASTRUCTURE쓰면됨
ac.getBean(빈이름, 타입)
ac.getBean(타입)
스프링빈이 없으면 예외발생
조회 성공 test:
- 조회하는 방식에서, 타입으로 interface말고 구체class를 넣어도 동작함. 그러나 이런식으로 조회하면, 유연성이 떨어지므로 잘 안쓴다는점 알아두기!
조회 실패 test:
ac.getBeansOfType()
를 사용하면 해당 타입의 모든 빈을 조회할 수 있음
중복 타입 만들기 위해서, 간이로 test안에 config class생성함 :
@Configuration
static class SameBeanConfig {
//간이로 만든 class니까 지금 이 text class안에서만 이 class를 쓰겠다는 의미로 static으로 선언한거임
//그리고, appconfig에는 중복타입이 없으니까 test가 안돼서, 지금 새로 만드는거임
//이런식으로 중복으로 만드는경우 있음. 예를들어 반환 파라미터가 다르다든가 ㅇㅇ
@Bean
public MemberRepository memberRepository1() {
return new MemoryMemberRepository();
}
@Bean
public MemberRepository memberRepository2() {
return new MemoryMemberRepository();
}
}
test fail :
@Test
@DisplayName("타입으로 조회 시 같은 타입이 둘 이상이면, 중복 오류가 발생한다")
void findBeanByTypeDuplicate() {
MemberRepository bean = ac.getBean(MemberRepository.class);
}
오류발생시 test는 성공하도록 코드 변경해서 살펴보기 :
@Test
@DisplayName("타입으로 조회 시 같은 타입이 둘 이상이면, 중복 오류가 발생한다")
void findBeanByTypeDuplicate() {
Assertions.assertThrows(NoUniqueBeanDefinitionException.class,
() -> ac.getBean(MemberRepository.class));
}
중복일때 하나만 잘 찾는법 = 이름으로! :
@Test
@DisplayName("타입으로 조회 시 같은 타입이 둘 이상 있으면, 빈 이름을 지정하면 된다")
void findBeanByName() {
MemberRepository memberRepository = ac.getBean("memberRepository1", MemberRepository.class);
org.assertj.core.api.Assertions.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);
org.assertj.core.api.Assertions.assertThat(beansOfType.size()).isEqualTo(2);
}
스프링 빈 조회 시, 만약 자식이 있다면 자식 타입도 함께 조회됨
config class에서 bean 만들때 rateDiscountPolicy bean의 타입을 rateDiscountPolicy로 안하고 DiscountPolicy로 함수 선언해놓는 이유는?
원래는 테스트 코드에 이런식으로 출력같은거 넣지 않음
bean 조회는 이정도만 알면됨
사실 applicationContext에서 getBean할일 없음. spring Container가 자동으로 의존관계 주입해주는거 씀.