SpringMVC子父容器源码剖析
一、子父容器启动流程
二、环境准备
-
在spring源码中创建一个新的module
-
build.gradle
plugins { id 'java' id 'war' } group 'com.dabing.springmvc' version '5.1.13.BUILD-SNAPSHOT' sourceCompatibility = 11 repositories { mavenCentral() } dependencies { compile(project(":spring-webmvc")) compile(project(":spring-tx")) compile(project(":spring-jdbc")) testCompile group: 'junit', name: 'junit', version: '4.12' }
-
web.xml (DispatcherServlet配置的请求时进行加载创建)
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" > <web-app> <display-name>Archetype Created Web Application</display-name> <!--spring容器配置--> <!--1. 配置全局初始化参数,让服务器启动加载spring的配置文件--> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </context-param> <!--2. Spring监听器,监听服务器的启动(在服务器启动的时候,创建spring容器)--> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!--springmvc配置--> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
-
springmvc.xml
<?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:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation=" http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd "> <!--开启controller扫描--> <context:component-scan base-package="com.dabing.controller"/> <!--配置springmvc的视图解析器--> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".jsp"/> </bean> <!-- 自动注册最合适的处理器映射器,处理器适配器(调用handler方法) --> <!-- <mvc:annotation-driven/>--> </beans>
-
ControllerDemo
@Controller @RequestMapping("/demo") public class ControllerDemo{ @RequestMapping("/handle01") public String handle01(String name, Map<String,Object> model) { System.out.println("++++++++handler业务逻辑处理中...."); Date date = new Date(); model.put("date",date); return "success"; } }
-
关联本地tomcat
-
启动tomcat,测试module
三、源码分析
3.1 SpringIOC容器
启动tomcat,加载web.xml,加载web.xml中的监听器,执行ContextLoaderListener,执行监听器中的initWebApplicationContext方法进行父容器初始化操作
因此在initWebApplicationContext方法中设置断点
进入创建Spring IOC容器方法
设置Spring IOC容器的父容器依赖
因为IOC容器已经是顶级容器了,所以其parent属性是null
进入到SpringIOC容器初始化的核心方法:refresh方法
3.2 SpringMVC容器
在web.xml中设置了DispatcherServlet被请求时,进行实例化操作
访问servlet的时候,首先要执行的就是init方法
访问触发init方法
初始化SpringMVC IOC容器
子容器调用setParent设置父容器的引用
四、总结
- SpringMVC容器持有SpringIOC容器的引用,可以访问父容器中定义的bean
- SpringIOC容器是顶级容器,因此没有持有SpringMVC容器的引用,不可以访问子容器中定义的bean