[Section3 - 등록된 모든 Bean 조회하기]

public class ApplicationContextInfoTest {

    AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);

    @Test
    @DisplayName("모든 빈 출력하기")
    void findAllBean(){
        // Spring Container안에서 관리되는 Bean들을 String array로 받아온다
        String[] beanDefinitionNames = ac.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) { //iter + tab
                Object bean = ac.getBean(beanDefinitionName);
                System.out.println("name = " + beanDefinitionName + "onject =" + bean);
            }
        }
    }

//결과는 아래와 같이 나온다.

흐흐.JPG

위의 getBeanDefinitionNames()를 이용하면 모든 등록된 bean들을 String array로 받아올수 있다. 그리고 for문을 이용해서 그 Array안에 있는 Bean들을 조회하면 된다. 그런데 위의 결과에서 내가 등록한 결과들 (hello.core.AppConfig도 bean으로 등록 된다) 말고도 Spring자체적으로 확장하기 위해 등록된 bean들까지 조회된다. 이것을 없애기 위해 다음과 같은 코드를 쓰면 된다.

@Test
    @DisplayName("Application 빈 출력하기")
    void findApplicationBean(){
        // Spring Container안에서 관리되는 Bean들을 String array로 받아온다
        String[] beanDefinitionNames = ac.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) { //iter + tab
            BeanDefinition beanDefinition = ac.getBeanDefinition(beanDefinitionName);

            if (beanDefinition.getRole() == BeanDefinition.ROLE_APPLICATION){
                //만약 Bean의 역할이 ROLE_APPLICATION 우리가 등록한 Bean인 경우에만 출력하게 한다.
                Object bean = ac.getBean(beanDefinitionName);
                System.out.println("name = " + beanDefinitionName + "onject =" + bean);
            }
        }
    }

마찬가지로 Container에서 bean들을 뽑는건 똑같은데 역할이 우리가 등록한 bean들인 (ROLE_APPLICATION)인 경우에만 출력하게 하면 된다. 만약 스프링 자체적으로 등록한 Bean을 검색하고 싶으면 ROLE_INFRASTRUCTURE로 바꿔주면 된다.

이렇게됨.JPG

그러나 위와같이 모든 Spring Bean을 조회할 일은 없을 것이다.

public class ApplicationContextBasicFindTest {

    AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);

    @Test
    @DisplayName("빈 이름으로 조회")
    void findBeanByName(){
        MemberService memberService = ac.getBean("memberService", MemberService.class);
        System.out.println("memberService = " + memberService);
        System.out.println("memberService.getClass() =" + memberService.getClass());

        //검증
        Assertions.assertThat(memberService).isInstanceOf(MemberServiceImpl.class);

    }

    @Test
    @DisplayName("이름 없이 타입으로만 조회")
    void findBeanByType(){ //빈 이름은 method이름으로 조회가 가능하다
        MemberService memberService = ac.getBean(MemberService.class);
        System.out.println(memberService);
        //검증
        Assertions.assertThat(memberService).isInstanceOf(MemberServiceImpl.class);
    }

    @Test
    @DisplayName("구체 타입으로 조회")
    void findBeanByName2(){ //빈 이름은 method이름으로 조회가 가능하다
        MemberService memberService = ac.getBean(MemberServiceImpl.class);
        System.out.println(memberService);
        //검증
        Assertions.assertThat(memberService).isInstanceOf(MemberServiceImpl.class);
    }
}

Spring Container안에 Bean들이 저장되어 있고 그것을 getter, setter를 이용해서 위와 같이 가져올수 있다. 방법은 등록된 bean의 이름을 검색해서 가져오는 것과 이름 없이 인터페이스 타입으로 조회하는 것 그리고 구체 타입으로 조회하는 것 3가지 방법이 존재하는데 각각 장단점이 존재한다.

(타입은 동일한 타입 둘 이상이 있을때 혼란스러워하고, 구체 타입은 다형성 원리에 위배)

앞서 얘기했었지만, Type으로 조회할때, 같은 type의 빈이 존재하면 예외가 터진다.

public class ApplicationContextSameBeanFindTest {

    AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SameBeanConfig.class);

    @Test
    @DisplayName("타입으로 조회시 같은 타입이 둘 이상 있으면, 중복 오류가 발생한다")
    void findBeanByTypeDuplicate(){
        MemberRepository bean = ac.getBean(MemberRepository.class);
    }

    @Configuration
    static class SameBeanConfig{

        @Bean
        public MemberRepository memberRepository1(){
            return new MemoryMemberRepository();
        }

        @Bean
        public MemberRepository memberRepository2(){
            return new MemoryMemberRepository();
        }
    }
}
org.springframework.beans.factory.NoUniqueBeanDefinitionException:
No qualifying bean of type 'hello.core.member.MemberRepository' available: expected single matching bean but found 2: memberRepository1,memberRepository2