스프링 컨테이너에 등록된 빈들을 조회하게 될 경우 사용하는 방법을 기록하고자 한다.
1. 모든 빈 조회
AnnotationConfigApplicationContext의 인스턴스인 ac로 부터 모든 스프링의 정보를 받기 위해서는
ac.getBeanDefinitionNames()를 실행하면 빈 이름을 모두 받아와서 ac.getBean(빈 이름) 을 통하면 빈을 조회 할 수 있다.
public class ApplicationContextInfoTest {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
@Test
@DisplayName("모든 빈 출력하기")
void findAllBean(){
String[] beanDefinitionNames = ac.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
Object bean = ac.getBean(beanDefinitionName);
System.out.println("bean = " + bean);
}
}
}
실행 결과 :
2. 애플리케이션 빈 조회
애플리케이션 빈이란 사용자가 직접 등록한 빈을 말한다.
public class ApplicationContextInfoTest {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
@Test
@DisplayName("어플리케이션 빈 출력하기")
void findApplicationBean(){
String[] beanDefinitionNames = ac.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
BeanDefinition beanDefinition = ac.getBeanDefinition(beanDefinitionName);
if(beanDefinition.getRole() == BeanDefinition.ROLE_APPLICATION){
Object bean = ac.getBean(beanDefinitionName);
System.out.println("name = "+beanDefinitionName+", object = " + bean);
}
}
}
}
ac를 통해 Bean의 definition 정보를 받는다.
BeanDefinition beanDefinition = ac.getBeanDefinition(beanDefinitionName)
그 이후 defintion 정보를 통해 Role을 조회 한다.
ROLE_APPLICATION : 직접 등록한 애플리케이션 빈
ROLE_INFRASTRUCTURE : 스프링이 내부에서 사용하는 빈
실행 결과 :
3.스프링 빈 조회 : 가장 기본적인 조회 방법
ac.getBean(빈 이름, 타입) or ac.getBean(타입) 으로 가능
public class ApplicationContextBasicFindTest {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
@Test
@DisplayName("빈 이름으로 조회")
void findBeanByName(){
MemberService memberService = ac.getBean("memberService", MemberService.class);
assertThat(memberService).isInstanceOf(MemberService.class);
}
@Test
@DisplayName("이름 없이 타입으로만 조회")
void findBeanByType(){
MemberService memberService = ac.getBean( MemberService.class);
assertThat(memberService).isInstanceOf(MemberService.class);
}
}
실행 결과 : 테스트 성공
assertThat(인스턴스 명).isInstanceOf(타입) : 해당 인스턴스가 타입과 동일한지 확인 하는 메소드 "org.assertj.core.api.Assertions"의 메소드
4. 동일한 타입이 둘 이상 있을때의 스프링 빈 조회
타입으로 조회시, 같은 타입의 스프링 빈이 둘 이상이면 오류가 발생한다. 이때는 빈 이름을 지정해야한다.
테스트를 위해 SameBeanConfig 클래스를 만들어 MemberRepository 의 타입을 2개 생성하였다.
public class ApplicationContextSameBeanFindTest {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SameBeanConfig.class);
@Test
@DisplayName("타입으로 조회시 같은 타입이 둘 이상 있으면, 중복 오류 발생")
void findBeanByTypeDuplicate(){
Assertions.assertThrows(NoUniqueBeanDefinitionException.class,
() -> ac.getBean(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);
}
@Configuration
static class SameBeanConfig {
@Bean
public MemberRepository memberRepository1() {
return new MemoryMemberRepository();
}
@Bean
public MemberRepository memberRepository2() {
return new MemoryMemberRepository();
}
}
}
동일한 타입의 빈이 있으면 "NoUniqueBeanDefinitionException"이 발생한다. 그렇기에 ac.getBeansOfType(타입)을 통해 해당 타입으로 구성된 빈의 정보를 Map 형식으로 받아 출력한다.
실행결과 :
4. 상속관계에 있는 스프링 빈 조회
위의 동일한 타입의 빈이 여러개 있을때와 동일하게 부모 타입으로 조회시 자식이 여러개 있다면 중복오류가 발생하게 된다. 그럴경우 빈의 이름을 지정하면 조회가 가능해진다.
public class ApplicationContextExtendsFindTest {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(TestConfig.class);
@Test
@DisplayName("부모 타입으로 조회시, 자식이 둘 이상있으면, 중복 오류가 발생")
void findBeanByParentTypeDuplicate(){
assertThrows(NoUniqueBeanDefinitionException.class,
()-> ac.getBean(DiscountPolicy.class));
}
@Test
@DisplayName("부모 타입으로 조회시, 자식이 둘 이상있으면, 빈 이름을 지정하면 된다")
void findBeanByParentTypeBeanName(){
DiscountPolicy rateDiscountPolicy = ac.getBean("rateDiscountPolicy", DiscountPolicy.class);
assertThat(rateDiscountPolicy).isInstanceOf(RateDiscountPolicy.class);
}
@Configuration
static class TestConfig{
@Bean
public DiscountPolicy rateDiscountPolicy(){
return new RateDiscountPolicy();
}
@Bean
public DiscountPolicy fixDiscountPolicy(){
return new FixDiscountPolicy();
}
}
}
실행 결과 : 테스트 성공
5. 상속관계에 있는 모든 스프링 빈 조회
부모의 타입으로 조회 하거나 혹은 Object로 조회하여도 모두 조회 가능하다.
Object를 조회할 경우, 스프링 내부의 빈까지 모두 조회 되어 버린다.
public class ApplicationContextExtendsFindTest {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(TestConfig.class);
@Test
@DisplayName("부모 타입으로 모두 조회하기")
void findAllBeanByParentType(){
Map<String, DiscountPolicy> beansOfType = ac.getBeansOfType(DiscountPolicy.class);
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();
}
}
}
실행 결과 :
'개발 > Spring' 카테고리의 다른 글
[Spring Cache] Spring boot 환경에서 Redis Cache 사용하기 (0) | 2023.02.15 |
---|---|
[Spring] Spring MVC 정리 (0) | 2022.12.23 |
[Spring] 스프링 코어 정리 2 - 어노테이션 (0) | 2022.10.31 |
[Spring] 스프링 코어 정리 1 (0) | 2022.10.12 |
[Spring] 스프링을 사용하는 이유? (0) | 2022.08.25 |