0%

(十二)SpringMVC学习笔记-SpringMVC与Spring整合问题&IoC容器关系

在进行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
<!-- 配置启动Spring IoC容器的Listener -->
<!-- needed for ContextLoaderListener -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<!-- Bootstraps the root web application context before servlet initialization -->
<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>用于指定不扫描的注解 -->
<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
<!-- 扫描指定包下的注解 ,use-default-filters="false"表示不默认扫描全部注解了-->
<context:component-scan base-package="com.shoto.springmvc" use-default-filters="false">
<!-- <context:include-filter>用于指定只扫描的注解 -->
<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容器的子容器。具体关系如下图示:
在这里插入图片描述

------ 本文结束------