public class AppConfig {
public Tire tire() {
Tire tire = new KoreaTire();
return tire;
}
public Car car() {
Car car = new Car(tire());
return car;
}
}
바로 전 업로드의 AppConfig 클래스
AppConfig 클래스는 런타임상에서 의존관계를 명시하는 클래스이다.
IoC를 가능하게 해 주고, DI를 해주는 클래스이다.
스프링에도 이와 같이 객체 간의 의존관계를 관리, 설정하는 것이 있다.
바로 IoC 컨테이너(=스프링 컨테이너)이다.
스프링 컨테이너란...?
객체 간의 의존 관계를 설정하고, 생명주기를 관리해 준다.
이 컨테이너에서 관리하는 객체를 빈(Bean)이라고 부른다.
빈(Bean)
- 스프링 컨테이너에 의해 관리되는 재사용 가능한 컴포넌트
- 인스턴스화된 객체를 말한다.
(객체는 모든 인스턴스를 대표하는 포괄적인 의미이고, 인스턴스는 어떤 클래스로부터 만들어진 것인지를 보다 강조하는 의미를 가지고 있다.)
왜 굳이 스프링 컨테이너를 사용해 빈을 관리할까?
자바에서 객체를 사용하기 위해서는 new 연산자 등으로 인스턴스를 만들어야 하는데,
객체지향언어인 자바의 특성을 잘 활용할 수 없게 된다.
(객체가 많이 생성되어 버린다면 서로를 참조하는 상황이 많이 발생할 것이고,
그에 따라 객체 간 의존 관계가 많아져 의존성이 높아지게 된다.)
객체 간의 의존성을 낮추기 위해 스프링 컨테이너를 사용하여 빈을 관리한다.
스프링 컨테이너의 동작 과정을 살펴보자!
1. 빈의 생성
스프링 컨테이너는 애플리케이션 시작 시, 빈의 정의를 보고 빈 객체를 생성한다.
우리는 service, controller, entity클래스를 작성할 때 상단에 어노테이션을 붙인다.
이 어노테이션들은 모두 내부에 @Component를 포함하고 있다.
스프링은 @Component 어노테이션이 붙어있는 모든 클래스들을 찾아, 그 클래스의 인스턴스를 만들고 Bean으로 등록해 준다.

2. 의존성 주입
빈이 생성되면 스프링 컨테이너는 빈 객체의 생성자를 보고 빈 객체들 간 의존관계를 맺어준다
@Service
public class MemberServiceImpl implements MemberService{
public MemberServiceImpl(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
}
위 코드는 MemberServiceImpl 빈 객체에 MemberRepository 빈 객체의 의존성을 주입해 준다.
3. 초기화
빈이 생성되면 스프링은 모든 빈을 초기화한다.
미리 런타임 상에서 의존성 문제가 생겨 종료되지 않도록 하여 의존성이 이상하면 애플리케이션이 실행도 안되게 막는 것이다.
4. 사용
애플리케이션에서 특정 객체가 사용될 때 스프링 컨테이너가 객체 대신 빈으로 등록한 해당 타입의 객체를 반환한다.
스프링은 빈 객체를 싱글톤으로 관리한다.
5. 소멸
애플리케이션이 종료될 때 스프링 컨테이너는 빈을 모두 소멸하는 메서드를 호출한다.
스프링 컨테이너의 구조에 대해 알아보자!

스프링 컨테이너는 BeanFactory와 ApplicationContext 인터페이스로 구현되어 있다.
BeanFactory
BeanFactory는 빈을 등록, 생성 조회 등 빈을 관리하며, 빈을 인스턴트화 할 수 있다.
@Bean 어노테이션이 붙은 메서드의 이름을 스프링 빈의 이름으로 사용하여 빈을 등록
ApplicationContext
ApplicationContext는
AnnotationConfigApplicationContext 클래스
@Configuration, @Bean, @ComponentScan, @Component 등의 어노테이션을 사용해 빈을 정의하고 이를 스캔하여 등록할 수 있는 기능을 제공한다.