
- Root WebApplicationContext
- 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 와 연결한다.
web.xml로 정의Java 로 정의:
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를 배포할 경우 사용되는 시나리오스프링 부트에서 컨텍스트가 초기화되는 방법
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.FrameworkServletinitServletBean()메소드가 실행된다.initWebApplicationContext()메소드가 실행된다.WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE로 등록된 attribute 를 조회한다. -> Root ContextsetParent()메소드를 호출해서 Root Context 와 연결한다.