본문 바로가기
Develop/Spring

[Spring/기본편] 스프링 빈 조회

by J-rain 2024. 3. 19.

 

스프링 빈 조회

class ApplicationContextBasicFindTest {
        AnnotationConfigApplicationContext ac = new
                AnnotationConfigApplicationContext(AppConfig.class);

        @Test
        @DisplayName("빈 이름으로 조회")
        void findBeanByName() {
            MemberService memberService = ac.getBean("memberService",
                    MemberService.class);
            assertThat(memberService).isInstanceOf(MemberServiceImpl.class);
        }

        @Test
        @DisplayName("이름 없이 타입만으로 조회")
        void findBeanByType() {
            MemberService memberService = ac.getBean(MemberService.class);
            assertThat(memberService).isInstanceOf(MemberServiceImpl.class);
        }

        @Test
        @DisplayName("구체 타입으로 조회")
            // 권장되지는 않음
        void findBeanByName2() {
            MemberServiceImpl memberService = ac.getBean("memberService",
                    MemberServiceImpl.class);
            assertThat(memberService).isInstanceOf(MemberServiceImpl.class);
        }

        @Test
        @DisplayName("빈 이름으로 조회X")
        void findBeanByNameX() {
            //ac.getBean("xxxxx", MemberService.class);
            Assertions.assertThrows(NoSuchBeanDefinitionException.class, () ->
                    ac.getBean("xxxxx", MemberService.class));
        }

    }

스프링 빈을 찾는 가장 기본적인 조회 방법

  • ac.getBean(빈이름, 타입)
  • ac.getBean(타입)
  • 조회 대상 스프링 빈이 없으면 예외 발생
    • NoSuchBeanDefinitionException: No bean named ‘xxxx’ available

 

동일한 타입이 둘 이상 있는경우

  • ac.getBeansOfType() 을 사용하면 해당 타입의 모든 빈을 조회가능
    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();
            }
        }
    }

 

 

 

빈 조회 - 상속관계

  • 부모 타입으로 조회하면, 자식 타입도 함께 조회된다.
  • 그래서 모든 자바 객체의 상위인 Object 타입으로 조회하면 모든 스프링 빈 조회한다,
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("특정 하위 타입으로 조회")
            // 권장x
        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);
            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();
            }
        }
    }

애플리케이션 컨텍스트에서 실제로 빈을 조회할 때는 거의없다. 하지만 가끔 순수 자바 애플리케이션에서 스프링 컨테이너를 생성하여 써야 될 일이 있고 자동 의존관계 주입에서 문제 없이 해결할 수 있다.

댓글