본문으로 바로가기

[Spring] Spring bean(빈) 조회 - 상속 관계

category Java/Spring 2022. 1. 20. 01:36
반응형

 

 

 

 

스프링 빈을 조회할 때,

부모 타입으로 조회 시, 자식 타입도 함께 조회된다.

 

 

그래서 모든 자바 객체의 최고 부모인 Object 타입으로 조회하면,

모든 스프링 빈을 조회한다.

 

 

 

 

상속 관계의 스프링 빈 조회에 대한 처리 방법을 테스트 코드로 작성해보자.

 

 

 

 

 

 

 

 

 

 


● 상속 관계 스프링 빈 조회  

 

 

 

 

 

상속 관계의의 스프링 빈들을 조회하는 테스트 코드를 작성한다.

 

 

 

 

 

ApplicationContextExtendsFindTest.java

package hello.core.beanfind;

import hello.core.discount.DiscountPolicy;
import hello.core.discount.FixDiscountPolicy;
import hello.core.discount.RateDiscountPolicy;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Map;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;

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);
    }

    @Test
    @DisplayName("특정 하위 타입으로 조회")
    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();
        }
    }
}

 

 

TestConfig 클래스를 임시로 생성하여

같은 타입(DicountPolicy)를 상속받는 빈들을 생성한다.

 

 

 

지정한 테스트 이름처럼

부모 타입으로 빈을 조회 시, 자식 타입이 둘 이상 있으면

NoUniqueBeanDefinitionException 예외가 발생한다.

 

 

 

이를 해결하기 위해 같은 타입의 빈 조회시,

빈 이름(rateDicountPolicy)을 통해 빈을 조회했다.

 

 

 

 

부모 타입(DiscountPolicy)의 빈을 모두 조회하고자 할 땐,

key, value를 통해 조회할 수 있다.

 

 

 

 

 

 

위 테스트의 결과는...

 

 

 

 

 

○ 부모 타입으로 모두 조회

 

 

 

○ 부모 타입으로 모두 조회(Object)

 

 

 

모두 통과와 동시에 DiscountPolicy 빈들을

key, value로 출력하는 것을 볼 수 있다.

 

 

 

Object 타입으로 조회할 시,

스프링 고유의 빈들(org.springframework,context...)도 출력되는 것을 볼 수 있다.

 

 

 

 

 

반응형