转:Spring MVC getServletConfigClasses和getRootConfigClasses

在不使用Web.XML中配置搭建spring MVC框架时,一般需要创建一个类来继承AbstractAnnotationConfigDispatcherServletInitializer,如下代码所示:

public class SpittrWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected Class[] getRootConfigClasses() {
        return new Class[] { RootConfig.class };
    }
    @Override
    protected Class[] getServletConfigClasses() {
        return new Class[] { WebConfig.class };
    }
    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }
}

其中有两个方法,getRootConfigClasses()getServletConfigClasses()一直让我很疑惑,两个方法的说明分别是:

  • getRootConfigClasses: Specify @Configuration and/or @Component classes to be provided to the root application context.(将有@Component注解或者@Component注解的配置类提供给根应用上下文)
  • getServletConfigClasses:Specify @Configuration and/or @Component classes to be provided to the dispatcher servlet application context.(将有@Component注解或者@Component注解的配置类提供给根应用上下文)

两者之间有什么区别呢?后来在Spring的官方文档中找到答案。在Spring的官方文档中有这样一段话提到:

ApplicationContext instances in Spring can be scoped. In the Web MVC framework, each DispatcherServlet has its own WebApplicationContext, which inherits all the beans already defined in the root WebApplicationContext. The root WebApplicationContext should contain all the infrastructure beans that should be shared between your other contexts and Servlet instances. These inherited beans can be overridden in the servlet-specific scope, and you can define new scope-specific beans local to a given Servlet instance.

文档连接
粗略翻译一下:

在Spring中,应用上下文(ApplicationContext)的实例是可以范围化(Scoped)的,在Web MVC框架中,每个DispatcherServlet都可以有自己的Web应用上下文(WebApplicationContext),每个DispatcherServlet自己的WebApplicationContext继承所有的在根应用上下文中的bean。根应用上下文应该包含在其他DispatcherServlet中会用到的bean,比如DataSource等,这些在根应用上下文中的bean可以在DispatcherServlet自己的WebApplicationContext中被重载。

在Spring MVC中我们其实是可以创建出多个DispatcherServlet的(只要创建多个继承自AbstractAnnotationConfigDispatcherServletInitializer的类即可)。而每个DispatcherServlet有自己的应用上下文(WebApplicationContext),这个应用上下文只针对这个DispatcherServlet有用。这也就是getServletConfigClasses的作用,获取这个DispatcherServlet的应用上下文的配置类。

而除了每个DispatcherServlet配置类的应用上下文之外,还有一个根应用上下文,这个应用上下文的作用是为了在多个DispatcherServlet之间共享Bean,比如数据源Bean,这就是getRootConfigClasses的作用,用于返回根应用上下文的配置类。Spring框架的机制会保证如果在当前DispatcherServlet的应用上下文中没有找到想要的bean时,会去根应用上下文中去找。

上两张官方文档中的图:这两张图片也阐述了两种用法。

图片1

这是其中的一种用法,当应用中有DispatcherServlet时,每个DispatcherServlet的bean如Controller,ViewResolver,HandlerMapping等,均在getServletConfigClasses返回的类中配置而一些公共的bean,如Services,Repository均在getRootConfigClasses返回的类中配置

图片2

这是另外一种用法,但应用中只有一个DispatcherServlet中时,可以将所有的bean配置均写在根应用上下文中。DispatcherServlet获取想要的bean时,如果没有在自己的应用上下文中找到,则会自动到根应用上下文中去找。

这也就是Spring MVC的ApplicationContext继承机制。