在进行Spring与SpringMVC的整合操作时,可能会需要加入Spring IoC容器。通常情况下,类似于数据源、事务、Service、Dao和整合其他框架的配置数据都是放在Spring 的配置文件中,而不是放在SpringMVC的配置文件中。
1. SpringMVC与Spring整合问题
下面在Hello World示例的基础上来演示整合时可能出现的问题。
1.首先在web.xml文件中配置启动Spring IoC容器的Listener,内容如下所示:
1 2 3 4 5 6 7 8 9 10
|
<context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param>
<listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
|
2.接着在src目录下创建Spring 的配置文件applicationContext.xml,具体内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd">
<context:component-scan base-package="com.shoto.springmvc"> </context:component-scan> </beans>
|
3.然后添加一个业务层类,具体代码如下所示:
1 2 3 4 5 6 7
| @Service public class CustomerService { public CustomerService() { System.out.println("CustomerService..."); } }
|
4.将CustomerService 类对象注入到处理器类HelloWorld中,处理器类的具体代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| @Controller public class HelloWorld {
@Autowired private CustomerService customerService; public HelloWorld() { System.out.println("HelloWorld Constructor..."); } @RequestMapping("/helloSpringMVC") public String hellowolrd() { System.out.println("Hello World"); return "success"; } }
|
5.请求响应之后,控制台输出如下的信息:
显然,处理器类HelloWorld和业务层类CustomerService类都被创建了两次,这是因为我们在SpringMVC的配置文件applicationContext-mvc.xml和Spring的配置文件applicationContext.xml都配置了<context:component-scan base-package=”com.shoto.springmvc”/>所造成的。
解决方法:
修改<context:component-scan base-package=”com.shoto.springmvc”/>的配置,使Spring 的 IOC 容器不应该扫描 SpringMVC 中的 bean, 对应的SpringMVC 的 IOC 容器不应该扫描 Spring 中的 bean。
具体配置如下所示:
applicationContext.xml的配置:
1 2 3 4 5 6
| <context:component-scan base-package="com.shoto.springmvc"> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/> <context:exclude-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/> </context:component-scan>
|
applicationContext-mvc.xml的配置:
1 2 3 4 5 6
| <context:component-scan base-package="com.shoto.springmvc" use-default-filters="false"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/> <context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/> </context:component-scan>
|
2. SpringMVC与Spring 两者Ioc之间的关系
在上面的示例中,我们将Spring IoC的bean CustomerService 注入到了 SpringMVC IoC的bean HelloWorld中,即 web 层容器可以引用service层容器的 Bean。但是反过来却是不行的,因为service层容器访问不到 web 层容器的 Bean。
其中Spring MVC web 层容器可作为 service层 Spring容器的子容器。具体关系如下图示: