对于具有纯Java配置的Spring webapp,有两个不同的上下文是否有意义?

时间:2015-07-08 09:17:17

标签: java spring spring-mvc spring-java-config

我是Spring Java配置的新手,并且想知道一些事情。

传统的Spring Web应用程序有两种不同的上下文,即根应用程序上下文和调度程序servlet上下文。根上下文基本上包含服务层之前的所有内容(持久性配置,如JPA和数据访问层)以及包含所有MVC和其他与Web相关的事物的servlet上下文。

Web上下文继承自根上下文,因此Web组件可以在根上下文中访问bean,但不能相反。

使用无XML配置和org.springframework.web.WebApplicationInitializer的现代方法,有两个不同的上下文仍然有意义吗?

让一些注释@Configuration类按层重组(例如一个用于数据访问层,一个用于服务层,一个用于Web层)并在同一个上下文中加载所有这些类似乎更简单,像这样:

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("/");
    }

}

但是,我已经看到了仍然创建根上下文的示例,并使用org.springframework.web.context.ContextLoaderListener管理其生命周期:

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模块),第二种方法是否带来了平衡额外复杂性的任何具体好处?什么是最佳做法?

2 个答案:

答案 0 :(得分:1)

您正在寻求建议,但距离意见不远。这个答案是对春天哲学的理解。

Spring 允许为非MVC部分和MVC部分使用不同的上下文,建议这样做,因为关注点分离(*)被认为是良好的做法。它从不强迫开发者去做。

可以将所有内容放在java配置的单个上下文中,与使用XML完成相同的操作

由您来了解该伪规则(2个上下文)是否与您的应用程序相关。如果您以后可以从Spring MVC迁移到另一个框架,那么 相关。如果您在一个大型组织中工作,其中不同的开发人员可以在MVC部分和非MVC部分上工作,那么 相关。如果它是一个非常简单的应用程序,只有一个单独的开发人员,并且很少有预期的演变,那么您当然可以将最佳实践与简单交换。

规则只是指导原则,开发人员必须知道必须遵守的时间以及何时可以忽略它们。它实际上取决于一般背景,项目规模,组织和一般经验。

(*)将模型部分(服务和持久性)与VC部分(用户界面)分开被认为是好的,因为:

  • 你可以(在理论上)改变UI部分,同时保持模型部分(从传统的WebApp迁移到胖客户端只是将UI更改为最小的RESTfull接口)
  • 您可以尽可能少地坚持开发和测试不同的层
  • 您可以在模型和ViewController部件上拥有不同的团队,并且能够完全分离责任
  • 可以通过公司规则强制执行

答案 1 :(得分:0)

1)每个应用程序的一个上下文可能只是Singleton反模式的另一个转世。基本上它是你的东西的单一范围,当你有很多bean,特别是模糊的依赖,它很快就会导致问题。

2)你可以根据需要实时构建和销毁子上下文,从而对长期存在的对象,事件层次结构等不太关心(尽管不是简单的webapps需要的东西)。