백기선님의 "스프링 프레임워크 입문" 인프런 강의를 수강한 후, 여러 글들을 참고하여 쓴 글입니다.
문제가 될 시 삭제하겠습니다.
컨테이너(Container)는 보통 인스턴스의 생명주기를 관리하며, 생성된 인스턴스들에게 추가적인 기능을 제공하도록 하는 것이라 할 수 있다. 스프링에도 객체를 생성하고 관리하고 책임지고 의존성을 관리해주는 컨테이너가 있는데, 그것이 바로 IoC 컨테이너(=스프링 컨테이너) 입니다.
인스턴스 생성부터 소멸까지의 인스턴스 생명주기 관리를 개발자가 아닌 컨테이너가 대신 해줍니다.
객체관리 주체가 프레임워크(Container)가 되기 때문에 개발자는 로직에 집중할 수 있는 장점이 있습니다.
1. BeanFactory
자바 객체(bean) 인스턴스를 생성, 설정, 관리하는 실질적인 컨테이너이다.
2. ApplicationContext
BeanFactory를 상속받고 있다. BeanFactory의 확장 버전이다. 상속받아서 구현한 대표적인 차이점은 BeanFactory는 지연로딩, ApplicationContext는 pre로딩이다.
두 클래스 모두 Bean을 생성하고, 관리하는 클래스이다.
Ioc 컨테이너가 관리하는 객체를 빈(Bean)이라고 하고,
스프링에서 빈(Bean)은 보통 싱글톤(Singleton)으로 존재한다.
싱글톤(Singleton) : 어떤 클래스가 최초 한번만 메모리를 할당하고(Static) 그 메모리에 객체를 만들어 사용하는 디자인 패턴
new 연산자로 생성하는 객체는 빈(Bean)이 아니고, ApplicationContext.getBean()으로 얻어질 수 있는 객체는 빈(Bean)이다.
즉, 스프링에서의 빈(Bean)은 ApplicationContext가 알고있는 객체, ApplicationContext가 만들어서 그 안에 담고있는 객체를 의미한다.
스프링에서 @ComponentScan 어노테이션과 @Component 어노테이션을 사용해서 빈을 등록하도록 하는 방법이다.
간단히 말하면 @ComponentScan 어노테이션은 어느 지점부터 컴포넌트를 찾으라고 알려주는 역할을 하고 @Component는 실제로 찾아서 빈으로 등록할 클래스를 의미한다.
IoC 컨테이너를 만들고 그 안에 빈을 등록할때 사용하는 인터페이스들을 라이프 사이클 콜백이라고 부른다.
라이프 사이클 콜백 중에는 @Component 어노테이션을 찾아서 이 어노테이션이 붙어있는 모든 클래스의 인스턴스를 생성해 빈으로 등록하는 작업을 수행하는 어노테이션 프로세서가 등록돼있다.
스프링 부트 프로젝트에서 @ComonentScan 어노테이션이 붙어있는 클래스가 이에 해당한다.
다음은 스프링의 PetClinic 예제 코드이다.
PetClinicApplication 클래스에 @SpringBootApplication 어노테이션이 붙어있는데
이 어노테이션은 내부적으로 @ComponentScan 어노테이션을 사용한다.
이 @ComponentScan 어노테이션은 어디서부터 컴포넌트를 찾아볼 것인지 알려주는 역할을 한다.
@ComponentScan이 붙어있는 클래스가 있는 패키지에서부터 모든 하위 패키지의 모든 클래스를 훑어보며 @Component 어노테이션(또는 @Component 어노테이션을 사용하는 다른 어노테이션)이 붙은 클래스를 찾는다.
스프링이 IoC 컨테이너를 만들때 위와 같은 과정을 거쳐 빈(Bean)으로 등록해주는 것이다.
스프링의 PetClinic 예제 코드에서
위의 클래스는 @Controller 어노테이션이 붙어있는데
내부적으로 @Component 어노테이션을 사용한다.
즉, OwnerController는 스프링에 의해 IoC 컨테이너에 빈으로 등록된다.
위와 같이 @Component 어노테이션을 사용하는 방법 말고도 빈(Bean) 설정파일에 직접 빈(Bean)으로 등록할 수 있다.
빈(Bean) 설정파일은 XML과 자바 설정파일로 작성할 수 있는데 최근 추세는 자바 설정파일을 좀 더 많이 사용한다.
자바 설정파일은 자바 클래스를 생성해서 작성할 수 있으며 일반적으로 xxxxConfiguration와 같이 명명한다.
그리고 클래스에 @Configuration 어노테이션을 붙인다.
그 안에 @Bean 어노테이션을 사용해 직접 빈(Bean)을 정의한다.
@Configuration
public class SampleConfiguration {
@Bean
public SampleController sampleController() {
return new SampleController;
}
}
sampleController()에서 리턴되는 객체가 IoC 컨테이너 안에 빈(Bean)으로 등록된다.
물론 이렇게 빈(Bean)을 직접 정의해서 등록하면 @Component 어노테이션을 붙이지 않아도 된다.
@Configuration 어노테이션을 보면 이 어노테이션도 @Component를 사용하기 때문에 @ComponentScan의 스캔 대상이 되고 그에 따라 빈(Bean) 설정파일이 읽힐때 그 안에 정의한 빈(Bean)들이 IoC 컨테이너에 등록되는 것이다.