woniper

Spring-MVC 읽기 #5. AbstractDispatcherServletInitializer와 AbstractAnnotationConfigDispatcherServletInitializer 본문

Spring

Spring-MVC 읽기 #5. AbstractDispatcherServletInitializer와 AbstractAnnotationConfigDispatcherServletInitializer

woniper1 2019. 1. 8. 07:41

이번 글은 AbstractContextLoaderInitializer 클래스의 하위 클래스인 AbstractDispatcherServletInitializer 클래스와 AbstractAnnotationConfigDispatcherServletInitializer 클래스를 살펴볼 것이다.

AbstractDispatcherServletInitializer

AbstractContextLoaderInitializer 클래스는 ContextLoader를 통해 root WebApplicationContext를 생성하고, 초기화(refresh)한다는 걸 이해했다. 마찬가지로 AbstractDispatcherServletInitializer 클래스는 DispatcherServlet을 생성하고 초기화한다.

AbstractDispatcherServletInitializer#registerDispatcherServlet

@Override
public void onStartup(ServletContext servletContext) throws ServletException {
    super.onStartup(servletContext);
    registerDispatcherServlet(servletContext);
}

protected void registerDispatcherServlet(ServletContext servletContext) {
    String servletName = getServletName();
    Assert.hasLength(servletName, "getServletName() must not return null or empty");

    WebApplicationContext servletAppContext = createServletApplicationContext();
    Assert.notNull(servletAppContext, "createServletApplicationContext() must not return null");

    FrameworkServlet dispatcherServlet = createDispatcherServlet(servletAppContext);
    Assert.notNull(dispatcherServlet, "createDispatcherServlet(WebApplicationContext) must not return null");
    dispatcherServlet.setContextInitializers(getServletApplicationContextInitializers());

    ServletRegistration.Dynamic registration = servletContext.addServlet(servletName, dispatcherServlet);
    if (registration == null) {
        throw new IllegalStateException("Failed to register servlet with name '" + servletName + "'. " +
                "Check if there is another servlet registered under the same name.");
    }

    registration.setLoadOnStartup(1);
    registration.addMapping(getServletMappings());
    registration.setAsyncSupported(isAsyncSupported());

    Filter[] filters = getServletFilters();
    if (!ObjectUtils.isEmpty(filters)) {
        for (Filter filter : filters) {
            registerServletFilter(servletContext, filter);
        }
    }

    customizeRegistration(registration);
}
  1. onStartup 메소드는 registerDispatcherServlet 메소드를 호출한다.
  2. WebApplicationContext를 생성(createServletApplicationContext) 한 후 FrameworkServlet을 생성(createDispatcherServlet(servletAppContext))한다.

    protected FrameworkServlet createDispatcherServlet(WebApplicationContext servletAppContext) {
        return new DispatcherServlet(servletAppContext);
    }
    • createDispatcherServlet 메소드는 DispatcherServlet 생성한다. WebApplicationContext을 생성자 주입한다.
    • DispatcherServlet은 FrontController 역할을 하며, Spring-MVC에서 가장 중요한 클래스라 이해하고 넘어가자. 자세한 설명은 다음 글에서.
    • FrameworkServlet은 DispatcherServlet의 상위 클래스다.

AbstractAnnotationConfigDispatcherServletInitializer

AbstractDispatcherServletInitializer 클래스의 하위 클래스인 AbstractAnnotationConfigDispatcherServletInitializer는 AbstractContextLoaderInitializer 클래스에서 생성되는 root WebApplicationContext의 구현체인 AnnotationConfigWebApplicationContext를 생성한다.

AbstractAnnotationConfigDispatcherServletInitializer#createRootApplicationContext

@Override
@Nullable
protected WebApplicationContext createRootApplicationContext() {
    Class<?>[] configClasses = getRootConfigClasses();
    if (!ObjectUtils.isEmpty(configClasses)) {
        AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
        context.register(configClasses);
        return context;
    }
    else {
        return null;
    }
}
  1. WebApplicationContext의 구현체인 AnnotationConfigWebApplicationContext 클래스를 return 한다.
  2. 설정 클래스를 등록한다. (AnnotationConfigWebApplicationContext#register 메소드)
    • AnnotationConfigWebApplicationContext는 @Annotation을 이용해 설정 가능한 ApplicationContext의 구현체다.

마무리

이 글에서 설명하는 클래스는 2가지 중요한 일을 한다.

  1. DispatcherServlet을 생성한다.
  2. WebApplicationContext의 구현체인 AnnotationConfigWebApplicationContext를 생성한다.

Spring-MVC의 시작 부터 현재 글까지 다시 한번 정리해보자.

  1. WAS는 ServletContainerInitializer를 실행한다.
  2. ServletContainerInitializer의 구현체인 SpringServletContainerInitializer는 WebApplicationInitializer를 실행한다.
  3. WebApplicationInitializer는 아래와 같은 세 개의 구현체가 있다.
    • AbstractContextLoaderInitializer는 ContextLoader를 이용해 WebApplicationContext를 초기화한다.
    • AbstractDispatcherServletInitializer는 DispatcherServlet을 생성하고 초기화한다.
    • AbstractAnnotationConfigDispatcherServletInitializer는 AnnotationConfigWebApplicationContext를 생성한다.

다음 글은 Spring-MVC의 핵심이라 할 수 있는 DispatcherServlet을 볼 예정이다.

Comments