@Configuration
@ComponentScan // 여러가지 정보에 컨테이너를 구성하는 데 필요한 hint들을 넣을 수 있음
public class HellobootApplication {
@Bean
public ServletWebServerFactory servletContainer() {
return new TomcatServletWebServerFactory();
}
@Bean
public DispatcherServlet dispatcherServlet() {
return new DispatcherServlet();
}
public static void main(String[] args) {
// 스프링 컨테이너 생성
AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext() {
@Override
protected void onRefresh() {
super.onRefresh(); // 생략 X
ServletWebServerFactory serverFactory = this.getBean(ServletWebServerFactory.class);
DispatcherServlet dispatcherServlet = this.getBean(DispatcherServlet.class);
dispatcherServlet.setApplicationContext(this);
WebServer webServer = serverFactory.getWebServer(servletContext -> {
servletContext.addServlet("dispatcherServlet",dispatcherServlet)
.addMapping("/*");
}); // 웹서버 생성
webServer.start(); // Tomcat Servelet Container 동작
}
};
applicationContext.register(HellobootApplication.class);
applicationContext.refresh(); // 컨테이너 초기화(빈 오브젝트 생성)
}
}
DispatcherServlet은 Applicationcontext의 빈을 가져온 다음 주입을 해줬는 데 삭제를 하면 SpringContainer를 어디에서도 지정해 준 것이 없는 데 동작할까? ⭕️
어떻게 DispatcherServlet이 SpringContainer를 통해 HelloController를 찾아와서 맵핑정보도 사용하고 웹 요청이 오면 호출하는 작업을 수행할까?
⇒ SpringContainer 때문에 작업 수행이 가능 ‼️
Type Hierarchy 보는 단축키 : ctrl + H
setApplicationContext(ApplicationContext applicationContext)
set이라고 되어있기 때문에 아마 내부 멤버 변수에 저장을 해주는 기능을 수행할 때 사용하하고 만든 인터페이스
빈을 Container가 등록하고 관리하는 중 Container가 관리하는 오브젝트를 빈에 주입을 해주는 라이프 사이클 메서드임
이 인터페이스를 구현한 클래스가 스프링에 빈으로 등록이되면 Factory Method에서 만들어지든 설정 파일을 만들어지든 Componenet Scanner에 의해 등록이 되든 상관없이 일단 컨테이너에 등록된 후에 이런 종류의 인터페이스를 구현 해놓고 있으면 SpringContainer는 인터페이스의 setter 메서드를 이용해서 주입 해줌
DispatcherServlet은 이게 등록이 되는 시점에 SpringContainer가 보니까 ApplicationContext를 내가 이 setter 메서드를 통해서 주입해줘야 되겠다 판단하고 넣어 줌
⇒ 그래서 명시적으로 생성자 또는 Setter 메서드를 직접 호출해서 넣지 않더라도 ApplicationContext를 가지고 있게 된 것
@RestController
public class HelloController implements ApplicationContextAware {
private final HelloService helloService;
public HelloController(HelloService helloService) {
this.helloService = helloService;
}
@GetMapping("/hello")
public String hello(String name) {
return helloService.sayHello(Objects.requireNonNull(name)) ;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println(applicationContext); // 서버를 띄우기만 해도 실행 됨 -> 스프링 컨테이너가 초기화되는 시점에 작업이 일어나기 때문
}
}
서버를 띄우기만 해도 실행 됨 -> 스프링 컨테이너가 초기화되는 시점에 작업이 일어나기 때문