getServletConfigClasses() 和 getRootConfigClasses()的不同点

getServletConfigClasses() 和 getRootConfigClasses()都是AbstractAnnotationConfigDispatcherServletInitializer的抽象方法,现在来看一下两者的区别。

Spring的ApplicationContext提供了加载多个(分层)上下文的功能,允许每个上下文集中在一个特定的层上,例如应用程序的Web层或中间层服务。

使用分层ApplicationContext的一个典型示例是,当我们在Web应用程序中有多个DispatcherServlet时,我们将分享一些常见的bean,例如它们之间的数据源。 这样,我们可以定义一个包含所有公共bean的Root ApplicationContext和从根上下文继承公共bean的多个WebApplicationContexts。

在Web MVC框架中,每个DispatcherServlet都有自己的WebApplicationContext,它继承了Root WebApplicationContext中已定义的所有bean。 可以在特定于servlet的作用域中重写这些继承的bean,并且可以为给定的Servlet实例定义新的作用域特定的bean。

图1Spring Web MVC中的典型上下文层次结构
Spring Web MVC中的典型上下文层次结构

如果您居住在单个DispatherServlet世界中,则此方案也可能只有一个根上下文:

Spring Web MVC中的单根上下文

Talk is cheap, Show me the code!

假设我们要开发一个Web应用程序,我们将使用Spring MVC,Spring Security和Spring Data JPA。对于这个简单的场景,我们至少会有三个不同的配置文件。一个WebConfig,包含我们所有与Web相关的配置,例如ViewResolvers,Controllers,ArgumentResolvers等。如下所示:

@EnableWebMvc
@Configuration
@ComponentScan(basePackages = "com.so.web")
public class WebConfig extends WebMvcConfigurerAdapter {
    @Bean
    public InternalResourceViewResolver viewResolver() {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setPrefix("/WEB-INF/views/");
        viewResolver.setSuffix(".jsp");

        return viewResolver;
    }

    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        final boolean DO_NOT_USE_SUFFIX_PATTERN_MATCHING = false;
        configurer.setUseSuffixPatternMatch(DO_NOT_USE_SUFFIX_PATTERN_MATCHING);
    }
}

在这里,我正在定义一个ViewResolver,来解析普通的jsp。我们需要一个RepositoryConfig,它包含所有数据访问工具,如DataSource,EntityManagerFactory,TransactionManager等。它可能如下所示:

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = "com.so.repository")
public class RepositoryConfig {
    @Bean
    public DataSource dataSource() { ... }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() { ... }

    @Bean
    public PlatformTransactionManager transactionManager() { ... }
}

还有一个包含所有安全相关内容的SecurityConfig!

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    @Autowired
    protected void configure(AuthenticationManagerBuilder auth) throws Exception { ... }

    @Override
    protected void configure(HttpSecurity http) throws Exception { ... }
}

为了将所有这些粘合在一起,我们有两种选择。首先,我们可以通过在根上下文中添加RepositoryConfig和SecurityConfig以及在其子上下文中添加WebConfig来定义典型的分层ApplicationContext:

public class ServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class<?>[] { RepositoryConfig.class, SecurityConfig.class };
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class<?>[] { WebConfig.class };
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }
}

由于我们在这里只有一个DispatcherServlet,我们可以将Web Config添加到根上下文并使servlet上下文为空:

public class ServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class<?>[] { RepositoryConfig.class, SecurityConfig.class, WebConfig.class };
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return null;
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }
}

Further Reading

Skaffman did a great job on explaining ApplicationContext hierarchies in this answer, which is highly recommended. Also, you can read Spring Documentation.

猜你喜欢

转载自blog.csdn.net/CmdSmith/article/details/81905946