✔︎ 스프링 컨테이너 생성

컨테이너에 등록된 빈 조회

hello.core.beanfind.ApplicationContextInfoTest.java

- 27줄에 ac.getBeandDefinition(beanDefinitionName) → bean에 대한 metadate 정보

- spring이 내부에서 사용하는 빈은 getRole()로 구분 가능 

  • ROLE_APPLICATION : 일반적으로 사용자가 정의한 빈
  • ROLE_INFRASTRUCTURE : 스프링이 내부에서 사용하는 빈

 

출력된 애플리케이션 빈

 

★ soutm → system.out.println 단축키 

 

✔︎ 스프링 빈 조회 - 기본

ApplicationContextBasicFindTest.java

- assertThat같은 경우는 검증하는것 

- asserThat의 경우 Assertions.assertThat에서 option+enter해서 on-demand로 Assertions를 없앰 (줄임말)

- 항상 test를 할때는 실패 test도 있어야해서 빈 이름으로 조회X test도 진행함

- 마지막 빈 이름으로 조회X부분에서는 () -> 뒷부분의 로직을 실행했을때 앞의 예외가 던져져야 함 

 

✔︎ 스프링 빈 조회 - 동일한 타입이 둘 이상부터 시작 

ApplicationContextSameBeanFindTest.java

package hello.core.beanfind;

import hello.core.member.MemberRepository;
import hello.core.member.MemoryMemberRepository;
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 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();
        }

    }

}

- getBean에서 option+command+v  → 앞부분 자동완성 

★ command + shifht + enter → 자동 세미콜론 생성

 

✔︎ 스프링 빈 조회 - 상속 관계

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(){
//        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("특정 하위 타입으로 조회")
    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);
//        beansOfType의 사이즈가 2개면 성공
        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();
        }
    }
}

 

✔︎ BeanFactory와 ApplicationContext

- BeanFactory

  • 스프링 컨테이너의 최상위 인터페이스
  • 스프링 빈을 관리하고 조회하는 역할 담당
  • getBean() 제공
  • 대부분의 기능을 제공

- ApplicationContext

  • BeanFactory 기능을 모두 상속받아서 제공
  • BeanFactory + 부가기능

➜ 결론

- ApplicationContext는 빈 관리기능 + 편리한 부가기능 제공

- BeanFactory나 ApplicationContext를 스프링 컨테이너라고 부름

 

✔︎ 다양한 설정 형식 지원 - 자바 코드, XML

XmlAppContext.java

- GenericXml ← xml이라는 문서를 설정정보로 사용

 

src/main/resources/appConfig.xml

- new-xml configuration file-spring config 에서 파일 생성

- <bean></bean> 빈 등록

 

✔︎ 스프링 빈 설정 메타 정보 - BeanDefinition

- BeanDefinition 

  • 역할과 구현을 개념적으로 나눈 것
  • xml이나 자바 코드를 읽어서 BeanDefinition을 만들 수 있음
  • 스프링 컨테이너가 자바코드인지 xml인지에 상관없이 BeanDefinition만 알면 됨
  • 스프링 컨테이너는 이 메타정보를 기반으로 스프링 빈을 생성 

BeanDefinitionTest.java

'개발 > spring' 카테고리의 다른 글

[스프링] 싱글톤 컨테이너  (0) 2024.04.26
[스프링] 스프링 핵심 원리 - 기본편 2  (0) 2023.11.27
[스프링] 스프링 핵심 원리 - 기본편 1  (0) 2023.11.27
[스프링] start  (0) 2023.11.06

+ Recent posts