스프링 IoC 컨테이너 생성 → 스프링 빈 생성 → 의존관계 주입 → 초기화 콜백 메소드 호출 → 사용 → 소멸 전 콜백 메소드 호출 → 스프링 종료
ApplicationContext
Spring framework에서는 스프링 컨테이너를 통해 객체(Bean)들을 관리한다.
여기서 스프링 컨테이너가 ApplicationContext이다.
● BeanFactory와 ApplicationContext
BeanFactory는 스프링 컨테이너의 최상위 인터페이스이며, 스프링 빈을 관리하고 조회하는 역할을 담당한다.
.getBean()과 같은 기능은 BeanFactory가 지원하는 기능이다.
ApplicationContext는 BeanFactory 기능을 모두 상속받아서 제공한다.
스프링 빈을 관리&조회하는 기능 외에도 앱 개발에 필요한 편리한 부가 기능들을 제공한다.
BeanFactory는 거의 사용하지 않고, ApplicationContext를 사용하기 때문에 ApplicationContext를 스프링 컨테이너라 한다.
자바 설정 클래스를 기반으로 스프링 컨테이너를 만들 수 있다.
new AnnotationConfigApplicationContext(AppConfig.class) -> ApplicationContext 인터페이스의 구현체
싱글톤 패턴이란 클래스의 인스턴스가 딱 1개만 생성되는 것을 보장하는 디자인 패턴인데,
스프링 컨테이너는 싱글턴 패턴을 적용하지 않아도, 객체 인스턴스를 싱글톤으로 관리한다.
빈(객체)를 스프링 컨테이너에 등록하고, 빈 조회 요청 시 새로 생성하지 않고 스프링 컨테이너에서 빈을 찾아서 반환한다.
스프링 빈 생성 및 등록 -> Component-Scan으로 Bean 등록
Injection
Setter, Field 주입 : 객체의 생성 ㅡ> 의존관계 주입으로 라이프 사이클이 나누어져 있음
즉, 생성자 주입과는 다르게 Controller 객체를 만들때 Service 객체와 의존 관계가 없어도 Controller 객체를 만들 수 있다.
따라서 객체 생성 → 의존 관계 주입의 단계로 나누어서 Bean LifeCycle 이 진행된다.
<br/>
- 생성자 주입 : 객체의 생성과 의존관계 주입이 동시에 일어남
### 왜 생성자 주입은 동시에 일어나는 것일까?
@Controller
public class CocoController {
private final CocoService cocoService;
public CocoController(CocoService cocoService) {
this.cocoService = cocoService;
}
}
자바에서 new 연산을 호출하면 생성자가 호출이 된다.
Controller 클래스에 존재하는 Service 클래스와의 의존관계가 존재하지 않는다면,
다음과 같이 Controller 클래스는 객체 생성이 불가능할 것이다.
public class Main {
public static void main(String[] args) {
// CocoController controller = new CocoController(); // 컴파일 에러
CocoController controller1 = new CocoController(new CocoService());
}
}
그렇기 때문에 생성자 주입에서는 객체 생성, 의존관계 주입이 하나의 단계에서 일어나는 것이다.
### 생성자 주입을 선택하라
- 대부분의 의존관계 주입은 최초 1회 주입후 해당 의존관계가 변경될 일이 없다. (불변)
- 그런데 수정자주입을 할 경우 setter(setXxx)를 public으로 열어야해서 변경 가능성이 생긴다.
Bean LifeCycle
ApplicationContext
스프링 빈 생성 및 등록 -> Component-Scan으로 Bean 등록
Injection
Setter, Field 주입 : 객체의 생성 ㅡ> 의존관계 주입으로 라이프 사이클이 나누어져 있음
setter 주입의 경우 Controller 객체를 만들 때 의존 관계는 필요하지 않다.
private CocoService cocoService;
@Autowired public void setCocoService(CocoService cocoService) { this.cocoService = cocoService; } }
@Controller public class CocoController { private final CocoService cocoService;
public CocoController(CocoService cocoService) { this.cocoService = cocoService; } }
public class Main { public static void main(String[] args) {
// CocoController controller = new CocoController(); // 컴파일 에러
CocoController controller1 = new CocoController(new CocoService()); } }