对于纯Java配置的SpringWebApp,有两个不同的上下文有意义吗?
我是SpringJava配置新手,我想知道一些事情 传统上SpringWebApps有两种不同的上下文,根应用程序上下文和DispatcherServlet上下文。根上下文基本上包含服务层(持久性配置,如JPA和数据访问层)的所有内容,servlet上下文包含所有MVC和其他与web相关的内容 web上下文继承自根上下文,因此web组件可以访问根上下文中的bean,但不能访问相反的bean 在使用无XML配置和对于纯Java配置的SpringWebApp,有两个不同的上下文有意义吗?,java,spring,spring-mvc,spring-java-config,Java,Spring,Spring Mvc,Spring Java Config,我是SpringJava配置新手,我想知道一些事情 传统上SpringWebApps有两种不同的上下文,根应用程序上下文和DispatcherServlet上下文。根上下文基本上包含服务层(持久性配置,如JPA和数据访问层)的所有内容,servlet上下文包含所有MVC和其他与web相关的内容 web上下文继承自根上下文,因此web组件可以访问根上下文中的bean,但不能访问相反的bean 在使用无XML配置和org.springframework.web.WebApplicationIniti
org.springframework.web.WebApplicationInitializer
的现代方法中,使用两种不同的上下文是否仍然有意义
似乎更简单的做法是,只需使用几个带注释的@Configuration
类按层重新组合bean(例如,一个用于数据访问层,一个用于服务层,一个用于web层),并在相同的上下文中加载所有bean,如下所示:
public class MyWebApplicationInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext container) {
// Create the dispatcher servlet's Spring application context
AnnotationConfigWebApplicationContext dispatcherServletContext = new AnnotationConfigWebApplicationContext();
dispatcherServletContext.register(MyPersistenceConfig.class, MyServicesConfig.class, MyMvcConfig.class);
// Register and map the dispatcher servlet
ServletRegistration.Dynamic dispatcher = container.addServlet("dispatcher", new DispatcherServlet(dispatcherServletContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
}
public class MyWebApplicationInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext container) {
// Create the 'root' Spring application context
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
rootContext.register(MyPersistenceConfig.class, MyServicesConfig.class);
// Manage the lifecycle of the root application context
container.addListener(new ContextLoaderListener(rootContext));
// Create the dispatcher servlet's Spring application context
AnnotationConfigWebApplicationContext dispatcherServletContext = new AnnotationConfigWebApplicationContext();
dispatcherServletContext.register(MyMvcConfig.class);
// Register and map the dispatcher servlet
ServletRegistration.Dynamic dispatcher = container.addServlet("dispatcher", new DispatcherServlet(dispatcherServletContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
}
但是,我看到过一些示例,其中仍然创建了根上下文,并使用org.springframework.web.context.ContextLoaderListener管理其生命周期,如下所示:
public class MyWebApplicationInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext container) {
// Create the dispatcher servlet's Spring application context
AnnotationConfigWebApplicationContext dispatcherServletContext = new AnnotationConfigWebApplicationContext();
dispatcherServletContext.register(MyPersistenceConfig.class, MyServicesConfig.class, MyMvcConfig.class);
// Register and map the dispatcher servlet
ServletRegistration.Dynamic dispatcher = container.addServlet("dispatcher", new DispatcherServlet(dispatcherServletContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
}
public class MyWebApplicationInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext container) {
// Create the 'root' Spring application context
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
rootContext.register(MyPersistenceConfig.class, MyServicesConfig.class);
// Manage the lifecycle of the root application context
container.addListener(new ContextLoaderListener(rootContext));
// Create the dispatcher servlet's Spring application context
AnnotationConfigWebApplicationContext dispatcherServletContext = new AnnotationConfigWebApplicationContext();
dispatcherServletContext.register(MyMvcConfig.class);
// Register and map the dispatcher servlet
ServletRegistration.Dynamic dispatcher = container.addServlet("dispatcher", new DispatcherServlet(dispatcherServletContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
}
对于一个简单的webapp(单maven模块),第二种方法是否带来了平衡额外复杂性的具体好处?最佳做法是什么?你在征求意见,但离意见不远。这就是我对春天哲学的理解
Spring允许对非MVC部件和MVC部件使用不同的Contexte,并建议这样做,因为关注点分离(*)被认为是一种良好的实践。它从不强迫开发人员这样做
在java配置中,您可以将所有内容放在单个上下文中,这与使用XML所做的完全相同
这取决于您是否知道该伪规则(2个contextes)与您的应用程序相关。如果您以后可以从SpringMVC转移到另一个框架,那么它就与之相关。如果您在一个大型组织中工作,不同的开发人员可以在MVC部件和非MVC部件上工作,那么是相关的。如果它是一个非常简单的应用程序,只有一个开发人员,并且几乎没有预期的发展,那么您当然可以与简单性交换最佳实践
规则只是指导原则,开发人员必须知道什么时候必须遵守规则,什么时候可以忽略规则。这实际上取决于总体环境、项目规模、组织结构和总体经验
(*)将模型部分(服务和持久性)与VC部分(用户界面)分离被认为是好的,因为:
- 您(理论上)可以在保留模型部分的同时更改UI部分(从传统WebApp迁移到胖客户端只是将UI更改为最小的RESTfull界面)
- 您可以尽可能少地开发和测试不同的层
- 您可以在模型和ViewController部件上组建不同的团队,并将职责进行清晰的分离
- 它可以由公司规则强制执行
1)每个应用程序的一个上下文可能会成为单身反模式的另一个转世。基本上,它是你的东西的单一作用域,当你有很多bean,特别是不明确的依赖项时,它很快就会导致问题
2) 您可以根据需要实时构建和销毁子上下文,从而减少对长期存在的对象、事件层次结构等的关注(尽管这不是简单的Web应用程序所需要的)谢谢Serge给出的一般答案。但我希望能从单独的上下文中获得更多类似于特定优势列表的东西,例如,我可以想到“您可以独立于web框架为您的服务层构建单元测试”,或者,如您所述,“您可以在将来更轻松地切换web framework”。如果你用那种方式编辑你的问题,我会接受你的答案。