- Spring IoC 컨테이너란?
- Spring IoC 컨테이너 종류
- Spring IoC 컨테이너의 생명 주기
- 객체(Bean)의 생성과 의존관계에 대한 관리(Control)를 사용자가 직접 하는 것이 아닌 스프링 컨테이너(외부)가 책임지는 구조를 의미한다.
- 스프링에서 IoC의 역할을 담당하고 있는 것이 IoC Container이다.
- 스프링을 사용할 때 다루고자 하는 객체를 담는 공간을 컨테이너라고 한다.
- 컨테이너는 객체의 생명주기를 관리하고 생성된 객체들에게 추가적인 기능을 제공한다.
-
스프링에서 객체(Bean)를 생성하고 의존성을 관리하는 컨테이너를 의미한다.
-
즉, IoC컨테이너는 단순히 객체의 생성뿐아니라 의존성 주입까지 한다는 의미를 포함하고 있다고 보면 된다.
-
XML, Java Configuration, Annotation 등의 방식을 사용하여 IoC 컨테이너를 설정할 수 있고, IoC 컨테이너가 생성하는 객체의 종류나 의존성 등을 유연하게 관리할 수 있다.
-
IoC Container를 사용하지 않았을 경우
- 자바 객체 생성 → 의존성 객체 생성(클래스 내부에서 생성) → 의존성 객체 메소드 호출
- 사용자가 작성한 코드에 따라 객체를 생성하고 의존관계를 주입한다.
public class Hello{
private Person person;
public Hello(){
person = new Person();
}
}
- IoC Container를 사용한 경우
- 스프링 객체 생성 → 의존성 객체 주입(제어권을 스프링에 위임하여 스프링이 만들어놓은 객체를 주입하게 한다) → 의존성 객체 메소드 호출
- 사용자가 별도의 어노테이션만 선언해주면 스프링의 IoC컨테이너가 알아서 객체(Bean)를 생성하고 의존관계를 주입해준다.
@Component
public class Hello{
private Person person;
@Autowired
public Hello(Person person){
this.person = person;
}
}
→ 스프링 IoC Container가 직접 객체를 생성하여 해당 객체에 주입 시켜주고 있다. 개발자가 해야 할 제어를 스프링 컨테이너에서 대신 해주고 있다. 그렇기에 제어의 역전(IoC)이라고 한다.
- 스프링은 IoC를 구현하기위해 보통 DI(Dependency Injection)을 사용한다.
- DI (의존성 주입) : 각 클래스 간의 의존 관계를 빈 설정 정보를 바탕으로 컨테이너가 자동으로 연결해주는 것이다.
-
BeanFactory
- IoC Container의 기본이 되는 인터페이스로, Bean을 관리하는 역할을 한다.
- Bean을 등록/생성/조회/반환한다.
- 보통은 BeanFactory를 바로 사용하지 않고 구현체인 ApplicationContext를 사용한다.
-
ApplicationContext
- BeanFactory를 구현하고 있는 클래스로, BeanFactory에 비해 더 많은 기능을 제공하고 있다.
- 메시지 소스를 활용한 국제화 기능 (MessageSource 인터페이스)
- 메시지에 대한 국제화를 제공하는 인터페이스이다.
- 메세지 설정 파일을 모아서 각 국가마다 로컬라이징을 함으로써 각 지역에 맞춤 메시지를 제공할 수 있는 것이다.
- 한국에서 들어오면 한국어로, 영어권에서 들어오면 영어로 출력한다.
- 환경 변수 구분 기능(EnvironmentCapable인터페이스)
- 로컬(내pc), 개발(테스트서버), 운영(실제 서비스) 등을 구분해서 처리
- 애플리케이션 이벤트 (ApplicationEventPublisher 인터페이스)
- 이벤트를 발행하고 구독하는 모델을 편리하게 지원 (’@EventListener’)
- 편리한 리소스 조회 (ResourceLoader 인터페이스)
- 파일, 클래스 패스, 외부 등에서 리소스를 편리하게 조회
- 메시지 소스를 활용한 국제화 기능 (MessageSource 인터페이스)
- ‘@Configuration’이 붙은 클래스들을 설정 정보로 등록해두고, ‘@Bean’이 붙은 메소드의 이름으로 Bean 목록을 생성한다.
- 싱글톤(하나의 인스턴스를 공유하여 사용)으로 객체를 생성, 관리한다.
- BeanFactory를 구현하고 있는 클래스로, BeanFactory에 비해 더 많은 기능을 제공하고 있다.
- 생성 → 빈 설정 → 사용 → 소멸
- IoC 컨테이너의 생명 주기는 애플리케이션이 시작될 때 시작되며, 애플리케이션이 종료될 때 함께 소멸한다.
- Resource 로딩
- IoC 컨테이너가 사용할 설정 파일(설정 정보)을 로드하는 단계이다. 설정 파일에는 어떤 객체를 생성하고 어떻게 의존성을 가질 지에 대한 정보가 포함되어 있어서, 이 설명서를 보고 사용할 Bean 객체를 정의할 수 있다.
- 이 단계에서 실제로 객체를 생성하지 않는다. 설정 파일의 정보들(Bean 객체 정보)을 메모리에 로드하고, 객체간의 의존성을 해결하는 일을 한다.
- Bean 설정
- Bean 객체를 구성하는 메타 데이터를 읽어들인다.
- 메타 데이터 내용으로는 Bean의 이름과 타입, 의존성, 생성자의 파라미터, 프로퍼티 값, 초기화와 소멸 메소드 등이 있다.
- 이런 정보들을 읽어서 IoC컨테이너가 사용할 수 있는 형태로 변환한다.
- Bean 인스턴스화
- Bean 설정 단계에서 변환한 정보를 기반으로 Bean 객체를 생성한다.
- 의존성 주입
- 생성한 Bean 객체 간의 의존성을 주입한다.
- Resource단계와 다른 점
- Bean들 간의 의존관계를 검사하고 메모리에 로드 할 뿐이다.
- 이번 단계에서는 객체가 생성되고, 실제로 Bean간의 의존성을 주입한다.
- Bean 초기화 콜백
- Bean 인스턴스가 생성된 후에, IoC 컨테이너가 빈을 초기화하기 위한 콜백 메서드를 호출한다.
- 초기화하는 이유는 생성자를 호출하는 것만으로 초기화할 수 없는 작업들이 존재하기 때문이다. 외부 리소스에 대한 연결 작업, 초기 데이터 로딩 작업과 같은 것들을 해야지만, 완전히 초기화되어 '사용 가능'한 상태가 될 수 있다
- ‘@PostConstruct’ 사용
-
Bean 사용
-
Bean 소멸 콜백
- 빈이 더 이상 필요하지 않을 때, IoC컨테이너는 빈의 소멸 메소드를 호출하고 해당 빈을 제거한다.
- ‘@PreDestroy’ 사용
- Resource 해제(컨테이너 종료)
- 컨테이너가 종료될 때 빈들도 함께 소멸된다.
[Reference]
- 컨테이너마다 제공해주는 기능이 다르다.
- 여기서 설명한 컨테이너는 IOC컨테이너이다.
- 추가적인 기능
- 빈의 생명주기 관리
- 객체를 빈으로 등록, 생성, 조회, 반환
- 국제화 기능
- 환경변수 구분 기능
- 애플리케이션 이벤트
- 편리한 리소스 조회
- 각 ‘@Bean’이 붙은 메소드마다 Bean이 이미 스프링 컨테이너에 등록되어 있는 경우 새로운 Bean을 생성하지 않고, 스프링 컨테이너에서 찾아서 이미 존재하는 Bean을 반환해준다. 스프링 빈이 없으면 새롭게 생성해서 스프링 빈으로 등록하고 반환한다.
- ‘@Autowired’필드 명 매칭
- 같은 타입 빈이 2개 이상 존재한다면 필드 이름으로 먼저 찾고, 중복된다면, 파라미터 이름으로 알맞은 빈을 의존성 객체로 생성한다.
- ‘@Qulifier’끼리 매칭
- 부가적인 이름을 붙여주고 생성자의 매개변수 앞에 ‘@Qualifier(부가적인 이름)’을 작성해주면 원하는 빈이 주입이 된다.
- ‘@Primary’
- 여러 빈이 존재한다면 ‘@Primary’가 붙은 빈이 우선권을 가진다.