A Bit on ApplicationContext
Hierarchies
春天的ApplicationContext
提供加载多个(分层)上下文的功能,允许每个上下文专注于一个特定层,例如应用程序的 Web 层或中间层服务。
使用层次结构的典型示例之一ApplicationContext
就是当我们有多个DispatcherServlet
在 Web 应用程序中,我们将分享一些常见的 Bean,例如datasources
它们之间。这样我们就可以定义一个根ApplicationContext
包含所有常见的 Bean 和多个WebApplicationContext
从根上下文继承通用 bean。
在Web MVC框架中,每个DispatcherServlet
有它自己的WebApplicationContext
,它继承了根中已经定义的所有beanWebApplicationContext
。这些继承的 bean 可以在特定于 servlet 的范围内被覆盖,并且您可以在给定的本地定义新的特定于范围的 beanServlet
实例。
Typical context hierarchy in Spring Web MVC (Spring Documentation)
如果你住在单身公寓DispatherServlet
world,对于这种情况也可能只有一个根上下文:
Single root context in Spring Web MVC (Spring Documentation)
Talk is cheap, Show me the code!
假设我们正在开发一个 Web 应用程序,并且将使用 Spring MVC、Spring Security 和 Spring Data JPA。对于这个简单的场景,我们至少有三个不同的配置文件。 AWebConfig
其中包含我们所有与网络相关的配置,例如ViewResolver
s, Controller
s, ArgumentResolver
s等。如下所示:
@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
基本上是为了解决我普通的旧jsps、糟糕的生活决定。我们需要一个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() { ... }
}
And a 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 { ... }
}
为了将所有这些粘合在一起,我们有两种选择。首先,我们可以定义一个典型的层次结构ApplicationContext
, 通过增加RepositoryConfig
and SecurityConfig
在根上下文中和WebConfig
在他们的孩子的背景下:
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
在这里,我们可以添加WebConfig
到根上下文并将 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
斯卡夫曼在解释方面做得很好ApplicationContext
此中的层次结构answer https://stackoverflow.com/a/5132637/1393484,强烈推荐。另外,您还可以阅读Spring文档 http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-servlet.