是否需要用Spring整合SpringMVC
是否需要用 Spring 整合 SpringMVC?或者更通俗地说,是否需要在 web.xml 文件中配置了SpringMVC IOC 容器的 DispatcherServlet 的同时,再去配置启动 Spring IOC 容器的 ContextLoaderListener?关于这个问题,答案通常是需要的。建议SpringMVC的配置文件只去配置SpringMVC需要的handler,而类似于数据源,事务,Service,Dao以及整合其他框架都是放在Spring的配置文件中(而不是放在 SpringMVC 的配置文件中)。
bean被创建两次?
当我们同时配置了SpringMVC和Spring的IOC容器,并且指定扫描相同的包,那么同一个Bean会被创建两次。而正确的情况应该为,Spring的IOC 容器不应该扫描SpringMVC中的bean, 对应的SpringMVC的IOC 容器不应该扫描Spring中的bean。有两种解决方法:
方法一:使Spring的IOC容器扫描的包和SpringMVC的IOC 容器扫描的包没有重合的部分。不过在实际情况下,项目的开发很可能是分模块进行的,所以这种方法并不总是适合。
方法二:在SpringMVC的IOC容器中指定只扫描由@Controller和@ControllerAdvice注解标记的bean:
同时在Spring的IOC容器中指定不扫描由@Controller和@ControllerAdvice注解标记的bean:
SpringMVC的IOC容器中的bean可以引用Spring的IOC容器中的bean,反之则不行
SpringMVC的IOC容器中的bean可以引用SpringIOC容器中的bean,例如,我们现在在SpringMVC的IOC容器中注册了一个Controller,名为HelloWorld,在SpringIOC的容器中注册了一个Service,名为UserService,那么现在我可以在HelloWorld中引用UserService的bean:
运行程序将输出:
但是我们却无法在UserService中引用HelloWorld的bean:
运行程序会报错:
这是因为多个Spring IOC 容器之间可以设置为父子关系,以实现良好的解耦。
Spring MVC的IOC作为WEB层容器,是业务层容器Spring IOC的子容器:即WEB 层容器可以引用业务层容器的Bean,而业务层容器却访问不到WEB 层容器的Bean,如下图所示:
实际上,从软件设计的层面来讲这也是符合逻辑的——Controller可以依赖Service,而Service却不能依赖Controller。