jhhan의 블로그

스프링 코어(2) - 스프링 컨테이너 & 빈 본문

Spring

스프링 코어(2) - 스프링 컨테이너 & 빈

jhhan000 2021. 1. 23. 23:07

저번에 적었던

스프링 코어(1) - 스프링 컨테이너 & 빈

포스트에 이어서 합니다.

 

 

이번엔 스프링 빈 조회 시 - 상속관계에 대해 알아보겠습니다.

  • 부모타입으로 조회 → 자식타입도 함께 조회
  • 최상위 객체인 Object로 조회 시, 모든 스프링 빈이 조회되어서 나오게 됩니다.

프로젝트 구조입니다.

beanfind 패키지 밑에 ApplicationContextExtendsFindTest라는 자바 클래스를 만듭니다.

    @Configuration
    static class TestConfig {
        @Bean
        public DiscountPolicy rateDiscountPolicy() {
            return new RateDiscountPolicy();
        }

        @Bean
        public DiscountPolicy fixDiscountPolicy() {
            return new FixDiscountPolicy();
        }
    }

먼저 이 코드를 작성합니다.

부모 타입이 DiscountPolicy이고, 자식 타입은 다릅니다.
(인터페이스와 구현체이죠)

이 TestConfig를 이용해서 진행합니다.

 

public class ApplicationContextExtendsFindTest {

    AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(TestConfig.class);

    @Configuration
    static class TestConfig {
        @Bean
        public DiscountPolicy rateDiscountPolicy() {
            return new RateDiscountPolicy();
        }

        @Bean
        public DiscountPolicy fixDiscountPolicy() {
            return new FixDiscountPolicy();
        }
    }

    @Test
    @DisplayName("부모 타입으로 조회 시 자식이 둘 이상 있으면, 중복 오류 발생")
    void findBeanByParentTypeDuplicate() {
        // DiscountPolicy dp = ac.getBean(DiscountPolicy.class); // 이 코드만 돌리면 오류 발생
        assertThrows(NoUniqueBeanDefinitionException.class, () -> ac.getBean(DiscountPolicy.class));
    }
}

코드를 작성합니다.

  • 맨 처음에 등장하는 AnnotationConfigApplicationContext ac ~~ : 이 부분 작성 잘 해주세요.
    TestConfig를 제대로 넣지 않으면 나중에 다르게 동작하기 때문에 유의하셔야 합니다.
  • 그럼 이제 첫번째 코드를 돌리기 전, 먼저 주석 처리한 부분을 해제한 후 돌려보세요.
  • 그러면 빨간색으로 에러가 발생했다고 뜰 것입니다.
  • 에러는 NoUniqueBeanDefinitionException이 발생합니다.
  • 설명에 적은대로 자식이 둘 이상이면 오류가 발생하는 것이죠.

 

    @Test
    @DisplayName("부모 타입으로 조회 시 자식이 둘 이상 있으면, 빈 이름을 지정하면 해결!")
    void findBeanByParentTypeBeanName() {
        DiscountPolicy rateDiscountPolicy = ac.getBean("rateDiscountPolicy", DiscountPolicy.class);
        assertThat(rateDiscountPolicy).isInstanceOf(RateDiscountPolicy.class);
    }
  • 부모 타입으로 조회를 하면 오류가 발생하기 때문에,
  • 빈 이름을 지정하면 해결됩니다.
  • 아까 적은 것 중에 fixDiscountPolicy를 대신 적어도 코드는 작동한다는 것은 대충 눈치채셨을 겁니다.
  • 실제 돌려보면 초록색으로 정상 동작하는 것을 볼 수 있습니다.

 

    @Test
    @DisplayName("특정 하위 타입으로 조회 - 추천 안 함")
    void findBeanBySubType() { // 구체적인 타입으로 지정했기 때문에 한 개만 조회됨
        RateDiscountPolicy rdp = ac.getBean(RateDiscountPolicy.class);
        assertThat(rdp).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));
        }
    }

  • 혹은 getBeansOfType으로 검색하면 부모타입으로 모두 검색할 수 있습니다.
  • 그 결과가 이미지와 같습니다.
  • 아까 TestConfig에 적은 rateDiscountPolicy, fixDiscountPolicy 2개가 모두 보이는 것을 확인할 수 있습니다.

 

그리고 Object 타입으로도 검색이 가능하다고 했습니다. 한번 해볼까요?

    @Test
    @DisplayName("부모 타입으로 모두 조회하기2")
    void findAllByBeanByObjectType() {
        Map<String, Object> beansOfType = ac.getBeansOfType(Object.class);
        for (String key : beansOfType.keySet()) {
            System.out.println("key = " + key + ", value = " + beansOfType.get(key));
        }
    }

  • Object로 검색한 결과입니다.
  • TestConfig에 적었던 2개 말고도 테스트를 진행하면서 실행되는 녀석들이 모두 등장했습니다.
  • 상당히 많네요.

 

이렇게 빈 조회에 대해서 알아봤는데,

사실 애플리케이션을 개발하면서 , Bean 조회를 할 일은 거의 없다고 합니다.

 

그래도 이렇게 알아보는 이유는

기본 기능이기 때문에, 알아두면 유익하기 때문입니다.

부모타입으로 조회시 자식까지 자동으로 조회되는 것을 알고 있다면

자동의존관계 주입을 진행할 때 어려움 없이 진행할 수 있기 때문입니다...

 

 

스프링과 빈 조회는 여기서 마치겠습니다.

그래도 빈 관련된 이야기는 앞으로 조금더 진행할 것 같습니다.

 

출처: 인프런 - 스프링 핵심원리(기본편) by 김영한