빈 등록
빈을 등록하기 위해서는 @Bean 설정된 메서드를 모두 호출하게 된다!!
스프링 컨테이너에 저장하기 위해서이다
ApplicationContext를 스프링 컨테이너라고 한다. 모든 걸 관리해준다.
AppConfig.class는 구성 정보가 저장된 클래스 (@Configuration)이다.
그래서 AppConfig에 있는 @Bean들을 모두 applicationContext라는 스프링 컨테이너에 저장(호출)을 한다.
여기서 이제 Bean을 get해야하는데, 이 때 getBean 메서드를 이용하여 가져온다.
이 때, getBean의 인자로는 Bean 이름과, 타입이 온다.
Bean을 저장할 때, 메서드 이름으로 저장하기 때문에 메서드 이름을 인자로 사용하면 된다.
스프링 컨테이너에 등록된 빈 들의 이름이다. 아래 사진을 보면 메서드 이름으로 저장되는 것을 알 수 있다.
컨테이너에 등록된 빈 조회
getBeanDefinitionNames
스프링 컨테이너에 등록된 모든 빈들의 이름을 가져온다.
getBean
스프링 컨테이너에 등록된 빈들의 객체 값? 주소?를 가져온다.
parameter로 타입만 올 수 있고, bean 이름과 타입이 올 수 있다.
getRole
해당하는 빈의 역할을 뽑아낸다. 사용자가 직접 등록한 빈인지, 스프링이 내부에서 사용하는 빈인지 알 수 있다.
getBeanDefinition
제일 아래 부분에서 언급
존재하지 않은 빈 조회
존재하지 않은 빈을 조회할 시, NoSuchBeanDefinitionException 예외가 발생하게 된다.
Test에서 예외가 발생하게 되면 Assertions.assertThrows을 사용하여 테스트를 실행하는데, 전에 사용했던
Assertions.assertThat과 다른 점이 있다.
assertThat은 import를 assertj.core.api를 하고, assertThrows는 junit.jupiter.api를 한다.
그리고 assertThrows는 인자로 람다식이 들어간다.
빈 조회할 때, 동일한 타입이 두 개 이상일 때
1. 만약 빈을 조회했는데, 같은 타입의 빈이 두 개 이상이면
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'hello.core.member.MemberRepository' available: expected single matching bean but found 2: memberRepository1,memberRepository2
NoUniqueBeanDefinitionException라는 예외가 발생하고, 친절한 스프링은 두 개의 빈이 조회됐다고 말을 해준다.
그렇다면 우리는 예외를 발생시키지 않기 위한 방법이 두 가지 있다.
빈 이름으로 지정하거나 특정 타입을 모두 조회하는 방법이 있다.
2. 특정 타입을 모두 조회하는 방법
스프링 컨테이너(ac)에서 특정 타입을 모두 조회하는 메서드인 getBeansOfType을 사용하면 된다. 그러면 Map 타입으로 조회가 된다.
햐당 기능은 나중에 자동 의존관계 주입 때 사용됨(아직 잘 모름)
상속 관계에 있을 때 빈을 조회하면 어떻게 될까?
상속 관계에서 부모 클래스의 빈을 조회하면 자식 클래스의 빈까지 모두 조회된다.
그래서 자식이 둘 이상 있으면 위의 같은 예외가 발생한다.
그래서 예외를 발생시키지 않기 위해 빈 이름을 지정하거나, 특정 자식 타입으로 조회할 수 있다.
부모 타입으로 모두 조회도 가능하며, Object 클래스를 조회하면 스프링에서 사용하는 모든 빈들을 출력할 수도 있다.
스프링 빈 설정 메타 정보 - BeanDefinition
메타 정보란 다른 데이터를 설명해 주는 데이터로, 데이터에 대한 데이터라고 한다.
(출처 : https://ko.wikipedia.org/wiki/%EB%A9%94%ED%83%80%EB%8D%B0%EC%9D%B4%ED%84%B0)
1. AppConfig 읽기
-> 스프링은 AppConfig를 어떻게 읽을까?
빈의 메타 정보를 가지고 있는 것이 BeanDefinition interface이다.
위의 reader로 AppConfig을 읽고 BeanDefiniton을 생성한다.
아래 값이 바로 BeanDefinition 값이다.
beanDefinitionName = memberService beanDefinition = Root bean: class [null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=appConfig; factoryMethodName=memberService; initMethodName=null; destroyMethodName=(inferred); defined in hello.core.AppConfig
그래서 우리는 위의 컨테이너에서 빈을 조회할 때, getBeanDefinition 메서드를 사용한다. 그러면 해당 빈의 메타 정보를 얻을 수 있다.
여기서 나는 왜 저 코드에서 역할을 조회할 때, ==연산자를 사용할까?라는 생각이 들어 레퍼런스를 찾아보았다.
보니까 역할을 조회할 때 반환값이 int 였던 것이다!! 그래서 == 연산자를 사용할 수 있었나보다라는 것을 알 수 있었다.
아무튼 정리를 해보면,
일단 빈의 메타 정보는 BeanDefinition이 가지고 있는데, 이 BeanDefinition은 AnnotationConfigApplicationContext의 안에 있는 AnnotatedBeanDefinitionReader가 AppConfig을 읽어서 생성하게 된다.
출처 : 인프런 스프링 핵심 원리 - 기본편 (김영한 강사님)
'Spring 강의 > 스프링 핵심 원리 - 기본편' 카테고리의 다른 글
스프링 핵심 원리 - 의존관계 자동 주입(2022.03.12 수정) (0) | 2021.08.06 |
---|---|
스프링 핵심 원리 - 컴포넌트 스캔 (0) | 2021.08.06 |
스프링 핵심 원리 - 싱글톤 컨테이너 (0) | 2021.08.04 |
스프링 핵심 원리 이해2 - 객체 지향 원리 적용 (0) | 2021.07.30 |
스프링 핵심 원리 이해1 - 예제 만들기 (0) | 2021.07.30 |