본문 바로가기
혼자 공부하는 것들/Spring

Spring 컨테이너에 등록된 bean 조회하기 테스트 코드[Juint5]

by applepick 2022. 1. 9.
반응형

 

스프링 컨테이너란?

자바 객체의 생명주기를 관리해주며, 생성된 자바의 기능을 제공해줍니다. 여기서 말하는 자바의 객체는  Spring에서 Bean이라고 불립니다. 스프링 컨테이너는 DI(의존성 주입), IoC가 적용됩니다.  대부분 객체들은 new, 인터페이스 생성을 통해, 개발자가 직접 의존성을 주입해줍니다. 이 역할을 스프링 컨테이너에 위임하는 것입니다.

스프링 컨테이너를 생성하면 스프링 컨테이너 안에 스프링 빈 저장소가 생성됩니다. 여기에 빈의 이름과, 빈객체 정보를 저장합니다. 개발자는 스프링 컨테이너에서 적용된 빈을 꺼내 활용합니다.


 

크게 Bean 컨테이너는 스프링 자체적인 Bean과 사용자가 생성한 Bean을 가지고 있습니다. 둘 다 출력하는 방법과 사용자의 Bean만 출력하는 방법을 작성해보았습니다. (Juint5에서부터는 class에 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("name = " + beanDefinitionName + " Object = "+ bean);
        }
    }
    @Test
    @DisplayName("애플리케이션 빈 출력하기")
    void findApplicationBean(){
        String[] beanDefinitionNames = ac.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            BeanDefinition beanDefinition =  ac.getBeanDefinition(beanDefinitionName);

            //등록한 애플리케이션만 출력할 수 있도록 해준다.
            //Role ROLE_APPLICATION: 직접 등록한 애플리케이션 빈
            //Role ROLE_INFRASTRUCTURE: 스프링이 내부에서 사용하는 빈
            if(beanDefinition.getRole() == BeanDefinition.ROLE_APPLICATION){
                Object bean = ac.getBean(beanDefinitionName); //타입이 지정이안되어있어서 오브젝트로 꺼낸다.
                System.out.println("name = " + beanDefinitionName + " Object = "+ bean);
            }
        }
    }
}

테스트코드 작성결과

 

여기서 의문점을 가질 수 있습니다.

위에 방식대로 빈의 반환 객체 타입이 똑같을 경우 

이런 식으로 NoUniqueBeanDefinitionException이 발생하게됩니다. 이것을 처리해주기 위해 Juint5에부터 assertThrows에 NoUniqueBeanDefinitionException을 명시해줘야 합니다.

빈의 반환 객체 타입이 똑같을 경우 어떻게 테스트 코드를 작성해야 할까?

같은 타입을 반환할 경우 Bean 이름을 지정해주면 됩니다.

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

    @Test
    @DisplayName("타입으로 조회시 같은 타입으로 둘이 있으면, 빈 이름을 지정하면 된다.")
    void findBeanByName(){
        Repository Repository = ac.getBean("RepositoryType1",Repository.class);
        assertThat(Repository).isInstanceOf(Repository.class);
    }
    
    @Configuration
    static class SameBeanConfig{ //static의 장점은 여기 스코프 안에서만 사용한다는 것

        @Bean
        public Repository RepositoryType1(){
            return new Repository();
        }
        @Bean
        public Repository RepositoryType2(){
            return new Repository();
        }
    }

스프링 컨테이너 안에 RepositoryType1과 RepositoryType2의 Bean이 있습니다. 반환 타입이 똑같습니다. 이럴 때는 get Bean에 Bean의 이름을 명시해주면 됩니다.

반응형

댓글