目录
1. Spring
容器 & SpringMVC
容器
1.1. Spring
容器 & SpringMVC
容器相同点
首先 SpringMVC
和 Spring
它俩都是容器,容器就是管理对象 bean
的地方,例如 Tomcat
就是管理 Servlet
对象的,而 SpringMVC
容器和 Spring
容器,就是管理 bean
对象的地方
直白的点,SpringMVC
就是管理 Controller
对象的容器,Spring
就是管理 Service
和 Dao
对象的容器,这下你明白了吧。所以我们在 SpringMVC
的 xml
配置文件里配置的扫描路径就是 Controller
的路径,而 Spring
的配置文件里自然配的就是Service
和 Dao
的路径。至于他是怎么管理起来的,又是怎么注入属性的,这就涉及到他们底层的实现技术了
SpringMVC
的 xml
配置文件配置
<context:component-scan base-package="com.example.controller">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
Spring
的 xml
配置文件配置
<context:component-scan base-package="com.atguigu">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
1.2. Spring
容器 & SpringMVC
容器不同点
其次,Spring
容器和 SpringMVC
容器的关系是父子容器的关系。Spring
容器是父容器,SpringMVC
是子容器;在子容器里可以访问父容器里的对象,但是在父容器里不可以访问子容器的对象,说的通俗点就是,在 Controller
里可以访问 Service
对象,但是在 Service
里不可以访问 Controller
对象
所以这么看的话所有的 bean
,都是被 Spring
或者 SpringMVC
容器管理的,他们可以直接注入,然后 SpringMVC
的拦截器也是 SpringMVC
容器管理的,所以在 SpringMVC
的拦截器里,可以直接注入 bean
对象
2. Web
容器
Web
容器是管理 Servlet
、监听器 Listener
和过滤器 Filter
的。这些都是在 Web
容器的掌控范围里。但他们不在 Spring
和 SpringMVC
的掌控范围里。因此,我们无法在这些类中直接使用 Spring
注解的方式来注入我们需要的对象,是无效的
Web
容器中有 Servlet
容器,Spring
项目部署后存在 Spring
容器和 SpringMVC
容器。其中 Spring
管理控制 Service
层和 Dao
层的 bean
对象;SpringMVC
容器控制 Controller
层 bean
对象;Servlet
容器控制 Servlet
对象
2.1. Spring
容器 & SpringMVC
容器 & Web
容器
- 项目启动时,首先
Servlet
初始化,初始化过程中通过web.xml
中Spring
的配置加载Spring
配置,初始化Spring
容器和SpringMVC
容器。待容器加载完成。Servlet
初始化完成,则完成项目启动
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0" metadata-complete="true">
<display-name>alipay-ssm</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:application-spring.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 解决post乱码 -->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- SpringMVC的前端控制器 -->
<servlet>
<servlet-name>itzixi-maven-ssm-alipay</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- contextConfigLocation不是必须的, 如果不配置contextConfigLocation, SpringMVC的配置文件默认在:WEB-INF/servlet的name+"-servlet.xml" -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:application-springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- 会拦截所有请求包括静态资源。需要在springmvc.xml中添加静态资源的映射 -->
<servlet-mapping>
<servlet-name>itzixi-maven-ssm-alipay</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
</web-app>
HTTP
请求到达Web
容器后,会到达Servlet
容器,容器通过分发器分发到具体的Spring
的Controller
层。执行业务操作后返回结果
2.2. Spring
容器 & SpringMVC
容器 & Web
容器的关系
Tomcat
在启动时给每个Web
应用创建一个全局的上下文环境,这个上下文就是ServletContext
,其为后面的Spring
容器提供宿主环境Tomcat
在启动过程中触发容器初始化事件,Spring
的ContextLoaderListener
会监听到这个事件,它的contextInitialized()
方法会被调用,在这个方法中,Spring
会初始化全局的Spring
根容器,这个就是Spring
的IOC
容器,IOC
容器初始化完毕后,Spring
将其存储到ServletContext
中,便于以后来获取Tomcat
在启动过程中还会扫描Servlet
,一个Web
应用中的Servlet
可以有多个,以SpringMVC
中的DispatcherServlet
为例,这个Servlet
实际上是一个标准的前端控制器,用以转发、匹配、处理每个Servlet
请求Servlet
一般会延迟加载,当第一个请求达到时,Tomcat & Jetty
发现DispatcherServlet
还没有被实例化,就调用DispatcherServlet
的init()
方法,DispatcherServlet
在初始化的时候会建立自己的容器,叫做SpringMVC
容器,用来持有SpringMVC
相关的bean
。同时,SpringMVC
还会通过ServletContext
拿到Spring
根容器,并将Spring
根容器设为SpringMVC
容器的父容器。注意,SpringMVC
容器可以访问父容器中的bean
,但是父容器不能访问子容器的bean
,也就是说Spring
根容器不能访问SpringMVC
容器里的bean
。说的通俗点就是,在Controller
里可以访问Service
对象,但是在Service
里不可以访问Controller
对象