본문 바로가기

Backend/Spring

[Spring] 스프링 컨테이너와 빈 1) 스프링 컨테이너 생성

728x90

 

목차

  • 스프링 컨테이너 생성
  • 컨테이너에 등록된 모든 빈 조회
  • 스프링 빈 조회 - 기본
  • 스프링 빈 조회 - 동일한 타입이 둘 이상
  • 스프링 빈 조회 - 상속 관계
  •  BeanFactory와 ApplicationContext
  • 다양한 설정 형식 지원 - 자바 코드, XML
  • 스프링 빈 설정 메타 정보 - BeanDefinition

 

 

스프링 컨테이너 생성 과정

*컨테이너 :사용하는 객체를 담고있는 것

 

다음 코드로 스프링컨테이너가 생성된다.

ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);

AppConfig 클래스를 파라미터로 넘기면, ApplicationContext를 반환해준다. 

ApplicationContext : 스프링 컨테이너 (인터페이스 → 다형성이 적용됨) 

AnnotationConfigApplicationContext : ApplicationContext 인터페이스의 구현체로 Annotation기반으로 만들어지는 스프링 컨테이너이다. 

(우리가 만든 AppConfig가 @Configuration annotation으로 만들어진 것이기 때문에 이를 매개변수로 사용)

xml기반의 애플리케이션 컨텍스트도 만들 수 있지만, 요즘에는 잘 사용되지 않는다. 

 

 

 

참고: 더 정확히는 스프링 컨테이너를 부를 때 BeanFactory , ApplicationContext 로 구분해서 이야기한다 BeanFactory 를 직접 사용하는 경우는 거의 없으므로 일반적으로 ApplicationContext 를 스프링 컨테이너라 한다. (뒤에서 설명)

∴ ApplicationContext가 스프링 컨테이너라고 생각해도됨 

 

 

1. 스프링 컨테이너 생성

AppConfig.class를 이용하여, 스프링 컨테이너가 만들어지면, 스프링 빈 저장소가 생성되며, key와 value값으로 나누어 저장된다 

구성정보는 매개변수로 넘어온 AppConfig를 사용한다. 

 

2. 스프링 빈 등록

스프링 컨테이너는 파라미터로 넘어온 설정 클래스(ex AppConfig)의 정보를 사용하여 스프링 빈을 등록한다.

 

빈 이름은 method의 이름을 사용하며, return으로 반환된 객체(구현체)를 빈 객체 (value)로 저장한다.

 

빈이름을 직접 부여할 수도 있다.

@Bean(name="원하는이름")

 

★빈이름은 항상 다른이름을 부여해야한다! 

 

 

3. 스프링 빈 의존관계 설정 - 준비단계

 

4. 스프링 빈 의존관계 설정 - 완료 

의존관계주입

(실제 스프링 라이프사이클로는 ) 스프링빈을 생성한 후, 설정관계를 참고하여 의존관계를 주입(DI)한다.(동시 발생 x) 

단순히 자바 코드를 호출하는 것이 아니다.

 

스프링 빈을 생성하고, 의존관계 주입 단계가 나누어진다. 하지만, 위의 그림처럼 자바코드로 스프링 빈을 등록하면, 생성자를 호출하면서 의존관계(매개변수가 호출되어 객체가 생성됨) 주입도 한번에 처리된다. (이는 의존관계 자동 주입에서 다시 설명) 

 

 

 

 

실제로 위에서 설명한 것 처럼 AppConfig를 이용해 스프링 빈을 등록하는 것을 직접확인해 보기 위해,

모든 빈을 출력해보기로 한다.

 

 

 

컨테이너에 등록된
빈(Spring Bean)
출력

 

 

테스트를 이용해 등록된 빈을 출력해본다.

테스트 하위에 beanfind 패키지를 생성하고, 그 하위에 ApplicationContextInfoTest클래스를 생성한다.

 

ApplicationContextInfoTest

package hello.core.beanfind;

import hello.core.AppConfig;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class ApplicationContextInfoTest {

    AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);


    @Test
    @DisplayName("모든 빈 출력하기")
    void findAllBean(){

        String[] beanDefinitionNames = ac.getBeanDefinitionNames(); // getBeanDefinitionNames 스프링에 등록된 모든 빈 이름 조회

        for (String beanDefinitionName : beanDefinitionNames) {
            Object bean = ac.getBean(beanDefinitionName); // getBean 빈 이름으로 빈 객체조회

            System.out.println("name = "+beanDefinitionName + " object = "+bean);
        }


    }
}

배열에 스프링빈을 담아와 iterator를 이용해 출력한다.

다음과 같이 등록이 되었음을 확인할 수 있다.

하지만, 모든 빈이 출력되기 때문에 스프링 내부에서 필요에 의해 가져온 빈도 출력된다.

 

 

 

개발자가 직접 생성해 등록하거나, 가져온 라이브러리 빈만 출력하고 싶은 경우에,

애플리케이션 빈이라고 하며 다음과 같이 getRole을 이용해, beanDefinition의 ROLE을 검사해주면 걸러낼 수 있다.

BeanDefinition.Role ROLE_APPLICAITON : 직접 등록한 애플리케이션 빈
BeanDefinition.ROLE_INFRASTRUCTURE : 스프링이 내부에서 사용하는 빈

 

 

    @Test
    @DisplayName("애플리케이션 빈 출력하기")
    void findApplicationBean(){

        String[] beanDefinitionNames = ac.getBeanDefinitionNames();

        for (String beanDefinitionName : beanDefinitionNames) {


            BeanDefinition beanDefinition = ac.getBeanDefinition(beanDefinitionName); //bean에대한 메타데이터 정보를 꺼낼 수 있는 메소드

            
            //Role ROLE_APPLICAITON : 직접 등록한 애플리케이션 빈
            //Role ROLE_INFRASTRUCTURE : 스프링이 내부에서 사용하는 빈 
            if(beanDefinition.getRole() == BeanDefinition.ROLE_APPLICATION){//해당 bean이 개발자가 등록한 외부라이브러리 / bean인가?
                Object bean = ac.getBean(beanDefinitionName);
                System.out.println("name = "+beanDefinitionName + " object = "+bean);
            }
        }


    }

 

 

 

728x90