[핵심원리][4-1] 스프링 컨테이너와 스프링 빈

kiteB·2021년 8월 23일
0

Spring 강의노트

목록 보기
12/24

Section 4. 스프링 컨테이너와 스프링 빈

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


[ 스프링 컨테이너 생성 ]

1. 스프링 컨테이너

  • ApplicationContext.java 파일을 통해서도 알 수 있듯이 ApplicationContext인터페이스이다.
  • 스프링 컨테이너는 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_APPLICATION: 직접 등록한 어플리케이션 빈
  • ROLE_INFRASTRUCTURE: 스프링이 내부에서 사용하는 빈

실행하면 다음과 같이 출력된다.

🔗 전체 코드 확인하기


[ 스프링 빈 조회 - 기본 ]

💡 스프링 컨테이너 스프링 빈을 찾는 가장 기본적인 방법

  • getBean(Bean이름, 타입)
  • getBean(타입)

내가 찾고자 하는 빈이 없다면 예외가 발생한다.
NoSuchBeanDefinitionException: No bean named 'xxxxx' available

예외 처리까지 끝낸 조회 코드

🔗 코드 확인하기


[ 스프링 빈 조회 - 동일한 타입이 둘 이상 ]

위에서 스프링 빈을 타입에 따라 조회하는 방법인 getBean(타입)에 대해 알아보았다.

만약 동일한 타입의 스프링 빈이 두 개 이상이라면?

NoUniqueBeanDefinitionException 예외가 발생한다!

해결법은 간단하다.

📌 해결 방법

  1. 빈 이름을 지정해준다.
  2. 해당 타입에 해당하는 빈을 모두 조회하고 싶은 것이라면, ac.getBeansOfType(타입)을 사용하면 예외가 발생하지 않는다.

🔗 코드 확인하기


[ 📘 오늘의 TIL 정리 ]

오늘 밤에 마저 합시다..

profile
🚧 https://coji.tistory.com/ 🏠

0개의 댓글