[TIL] #4. 스프링 컨테이너와 스프링 빈 ①

Section 4. 스프링 컨테이너와 스프링 빈
지난 시간에 ApplicationContext를 스프링 컨테이너라고 부른다고 했다.
이번 섹션에서는 이 스프링 컨테이너가 생성되는 과정에 대해 알아볼 것이다.

✔ 스프링 컨테이너 생성
1. 스프링 컨테이너
 
- ApplicationContext.java파일을 통해서도 알 수 있듯이- ApplicationConfig는 인터페이스이다.
- 스프링 컨테이너는 XML을 기반으로 만드는 방법과 애노테이션 기반의 자바 설정 클래스로 만드는 방법, 이렇게 두 가지가 있다.
- 요즘에는 XML으로 잘 만들지 않고 애노테이션 기반의 자바 설정 클래스로 만든다.왜일까 ❓ 
 XML설정에 대한 부담이 있고, 프로젝트 규모가 커지면 유지보수성이 낮아지게 된다!
💡 스프링 컨테이너
엄밀히 따지자면 스프링 컨테이너를
BeanFactory,ApplicationContext로 분리해서 불러야 한다. 하지만BeanFactory를 직접 사용하는 경우는 거의 없어서 보통ApplicationContext를 스프링 컨테이너라고 한다.
2. 스프링 컨테이너 생성 과정
✔ 스프링 컨테이너 생성
 
빈 이름 →
key, 빈 객체 →value
스프링 컨테이너를 생성할 때 구성 정보를 지정해줘야해서 AppConfig.class를 구성 정보로 지정해주었다.
✔ 스프링 빈 등록
 
전달받은 구성 정보, AppConfig을 사용해서 스프링 빈을 등록한다.
오른쪽의 빈 이름은 구성 정보의 메서드 이름을 사용하는데, 다른 이름으로 지정하고 싶으면 원하는 이름으로 설정해도 된다.
단, 이름을 중복으로 하면 에러가 발생하므로 괜히 나중에 고생하지 말고 처음 정할 때부터 잘 정하자😵
✔ 스프링 빈 의존관계 설정
 
이제 스프링 컨테이너는 설정 관계를 참고해서 의존관계를 주입(DI)해준다.
📌 참고
지금까지 스프링은 빈을 생성하고, 의존관계를 주입하는 단계가 있는데 사실은 이해를 돕기 위해 이렇게 나눈 것이다.
자바 코드로 스프링을 등록하면 생성자를 호출하면서 의존관계 주입도 처리된다.
✔ 컨테이너에 등록된 모든 빈 조회
AppliccationContextInfoTest.java 파일을 만들어서 컨테이너에 등록된 모든 빈을 조회해보자.
    @Test
    @DisplayName("모든 빈 출력하기")
    void findAllBean() {
        String[] beanDefinitionNames = ac.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            Object bean = ac.getBean(beanDefinitionName);
            System.out.println("name = " + beanDefinitionName + "object = " + bean);
        }
    }📌 모든 빈 조회하기
ac.getBeanDefinitionNames(): 스프링에 등록된 모든 빈 이름 조회
ac.getBean(Bean 이름):Bean 이름을 인자로 넘겨서 빈 객체(인스턴스) 조회
실행해보면 이렇게 모든 빈이 조회된다.

그런데 사실 내가 등록한 빈은 memberServiceobject 부터 discountPolicyobject 까지다.
그 위에 출력되는 것들은 스프링의 기능을 위해 생성된 것들이다.
그래서 만약 내가 만든 빈만 출력하고 싶다면 다음과 같이 작성해보자!
    @Test
    @DisplayName("애플리케이션 빈 출력하기")
    void findApplicationBean() {
        String[] beanDefinitionNames = ac.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            BeanDefinition beanDefinition = ac.getBeanDefinition(beanDefinitionName);
            //Role ROLE_APPLICATION: 직접 등록한 애플리케이션 빈
            //Role ROLE_INFRASTRUCTURE: 스프링이 내부에서 사용하는 빈
            if (beanDefinition.getRole() == BeanDefinition.ROLE_APPLICATION) {
                Object bean = ac.getBean(beanDefinitionName);
                System.out.println("name = " + beanDefinitionName + "object = " + bean);
            }
        }
    }📌 애플리케이션 빈 조회하기
Role ROLE_APPLICATION: 직접 등록한 애플리케이션 빈
Role ROLE_INFRASTRUCTURE: 스프링이 내부에서 사용하는 빈
실행하면 다음과 같이 출력된다.
 
✔ 스프링 빈 조회 - 기본
💡 스프링 컨테이너 스프링 빈을 찾는 가장 기본적인 방법
getBean(Bean이름, 타입)
getBean(타입)
내가 찾고자 하는 빈이 없다면 예외가 발생한다.
NoSuchBeanDefinitionException: No bean named 'xxxxx' available
예외 처리까지 끝낸 조회 코드
🔗 코드 확인하기
✔ 스프링 빈 조회 - 동일한 타입이 둘 이상
위에서 스프링 빈을 타입에 따라 조회하는 방법인 getBean(타입)에 대해 알아보았다. 
만약 동일한 타입의 스프링 빈이 두 개 이상이라면?
NoUniqueBeanDefinitionException 예외가 발생한다!
해결법은 간단하다.
📌 해결 방법
- 빈 이름을 지정해준다.
ac.getBeanType()을 사용하면 예외 없이 해당 타입의 모든 빈을 조회할 수 있다.
🔗 코드 확인하기
📘 오늘의 TIL 정리

오늘 밤에 마저 합시다..
Author And Source
이 문제에 관하여([TIL] #4. 스프링 컨테이너와 스프링 빈 ①), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@mmy789/TIL-4.-스프링-컨테이너와-스프링-빈저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
                                
                                
                                
                                
                                
                                우수한 개발자 콘텐츠 발견에 전념
                                (Collection and Share based on the CC Protocol.)