til
til copied to clipboard
Root, Servlet WebApplicationContext
- Root WebApplicationContext
- Servlet 에 의해 생성
- Servlet WebApplicationContext
- DispatcherServlet 에 의해 생성
- Servlet WebApplicationContext 에서 빈을 조회할 수 없는 경우 Root WebApplicationContext를 조회
web.xml
로 정의
<web-app>
<!-- Root -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/root-context.xml</param-value>
</context-param>
<!-- Servlet -->
<servlet>
<servlet-name>app1</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/app1-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>app1</servlet-name>
<url-pattern>/app1/*</url-pattern>
</servlet-mapping>
</web-app>
Java 로 정의:
public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
// Root
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[] { RootConfig.class };
}
// Servlet
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[] { App1Config.class };
}
@Override
protected String[] getServletMappings() {
return new String[] { "/app1/*" };
}
}
web.xml
대신 자바 정의를 사용할 수 있는 이유
- 서블릿 컨테이너가 초기화 될 때
spring-web
에서 정의한org.springframework.web.SpringServletContainerInitializer
가 실행된다.-
javax.servlet.ServletContainerInitializer
를 구현 -
@HandleTypes
값으로org.springframework.web.WebApplicationInitializer
를 지정 - 서블릿이 클래스패스에 존재하는
org.springframework.web.WebApplicationInitializer
의 구현체를 스캔해서onStartup
메소드의 파라미터로 전달
-
-
AbstractAnnotationConfigDispatcherServletInitializer
는org.springframework.web.WebApplicationInitializer
를 구현 -
org.springframework.web.SpringServletContainerInitializer
가 여러개의org.springframework.web.WebApplicationInitializer
를 호출하는 방식으로 작동한다. - 서블릿 컨테이너에
war
를 배포할 경우 사용되는 시나리오
스프링 부트에서 컨텍스트가 초기화되는 방법
- 스프링 부트는 Embedded Tomcat 을 사용하기 때문에 위 시나리오와는 다른 방식으로 스프링 컨테이너가 초기화된다.
- 스프링 컨테이너가 초기화 된 뒤 내장 톰캣이 실행된다.
-
org.springframework.web.SpringServletContainerInitializer
대신org.springframework.boot.web.servlet.ServletContextInitializer
를 구현하는 빈을 등록한다. - 스프링 부트에서는
org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext
를 사용한다.-
createWebServer()
에서 웹 서버를 생성하고 -
org.springframework.boot.web.servlet.ServletContextInitializer
를 찾아서 서블릿 컨텍스트를 초기화하는데 사용한다. -
org.springframework.boot.web.servlet
패키지에 있는~RegistrationBean
은org.springframework.boot.web.servlet.ServletContextInitializer
를 상속받는다. -
ServletRegistrationBean
,FilterRegistrationBean
,ServletListenerRegistrationBean
을 사용해서 서블릿 컨테이너를 초기화 할 수 있다.
-
Root WebApplicationContext 와 Servlet WebApplicationContext 가 연결되는 지점:
-
DispatcherServlet
은FrameworkServlet
을 상속 받는다 -
AnnotationConfigApplicationContext
는GenericApplicationContext
를 상속받는다. -
WebApplicationInitializer
를 구현한WebApplicationInitializer
의registerDispatcherServlet(ServletContext servletContext)
메소드에서DispatcherServlet
을 생성한다. -
javax.servlet.GenericServlet
의init(ServletConfig config)
메소드가 실행된다 -
org.springframework.web.servlet.HttpServletBean
의init()
메소드가 실행된다. -
org.springframework.web.servlet.FrameworkServlet
-
initServletBean()
메소드가 실행된다. -
initWebApplicationContext()
메소드가 실행된다.- 서블릿 컨텍스트에서
WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE
로 등록된 attribute 를 조회한다. -> Root Context - DispatcherServlet에 생성된 WebApplicationContext 객체의
setParent()
메소드를 호출해서 Root Context 와 연결한다.
- 서블릿 컨텍스트에서
-
Servlet Context Initialization
- https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#web.servlet.embedded-container.context-initializer
Context Hierarchy
- https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc-servlet-context-hierarchy