springmvc也是在spring framework中的,不是一个单独的项目
MVC就是和Tomcat有关。
01.MVC启动的第一步,启动Tomcat(这个和springboot的run方法启动Tomcat有关)
02.SpringMVC中,最为核心的就是DispatcherServlet,在启动Tomcat的过程中:
- Tomcat会先创建DispatcherServlet对象(这一步在手写springboot框架中已经写到,Tomcat在启动的时候会启动DispatcherServlet)
- 然后调用DispatcherServlet对象的init()
DispatcherServlet对象的init()
01.DispatcherServlet类的init()
public class DispatcherServlet extends FrameworkServlet {
//DispatcherServlet中没有init方法,在父类中找
}

HttpServletBean类
@Override
public final void init() throws ServletException {
// 解析 init-param 并封装只 pvs 中(xml)
PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);
if (!pvs.isEmpty()) {
try {
// 将当前的这个 Servlet 类转化为一个 BeanWrapper,从而能够以 Spring 的方法来对 init-param 的值进行注入
BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());
bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment()));
initBeanWrapper(bw);
// 属性注入
bw.setPropertyValues(pvs, true);
}
catch (BeansException ex) {
if (logger.isErrorEnabled()) {
logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex);
}
throw ex;
}
}
// Let subclasses do whatever initialization they like.
// 初始化Servlet,创建Spring容器
initServletBean();
}
DispatcherServlet 继承 httpservletbean
02.FrameworkServlet
public static final Class DEFAULT_CONTEXT_CLASS = XmlWebApplicationContext.class;
03.initServletBean
protected final void initServletBean() throws ServletException {
getServletContext().log("Initializing Spring " + getClass().getSimpleName() + " '" + getServletName() + "'");
if (logger.isInfoEnabled()) {
logger.info("Initializing Servlet '" + getServletName() + "'");
}
long startTime = System.currentTimeMillis();
try {
this.webApplicationContext = initWebApplicationContext();
// 空方法,无实现·
initFrameworkServlet();
}
catch (ServletException | RuntimeException ex) {
logger.error("Context initialization failed", ex);
throw ex;
}
if (logger.isDebugEnabled()) {
string value = this.enableLoggingRequestDetails ?
"shown which may lead to unsafe logging of potentially sensitive data" :
"masked to prevent unsafe logging of potentially sensitive data";
logger.debug("enableLoggingRequestDetails='" + this.enableLoggingRequestDetails +
"': request parameters and headers will be " + value);
}
if (logger.isInfoEnabled()) {
logger.info("Completed initialization in " + (System.currentTimeMillis() - startTime) + " ms");
}
}
04initWebApplicationContext
protected WebApplicationContext initWebApplicationContext() {
// 获得ContextLoaderListener存的父容器
WebApplicationContext rootContext =
WebApplicationContextUtils.getWebApplicationContext(getServletContext());
WebApplicationContext wac = null;
if (this.webApplicationContext != null) {
// 获得子容器
wac = this.webApplicationContext;
if (wac instanceof ConfigurableWebApplicationContext) {
ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac;
if (!cwac.isActive()) {
// 如果没有设置父容器 spring doGetBean
if (cwac.getParent() == null) {
cwac.setParent(rootContext);
}
// 配置并且加载子容器
configureAndRefreshWebApplicationContext(cwac);
}
}
}
if (wac == null) {
// 从servlet上下文根据名字从域里面获取
wac = findWebApplicationContext();
}
if (wac == null) {
// xml会在这里创建
wac = createWebApplicationContext(rootContext);
}
//refreshEventReceived 它会在容器加载完设置为true (通过事件onApplicationEvent)
// springboot在这初始化组件
if (!this.refreshEventReceived) {
synchronized (this.onRefreshMonitor) {
onRefresh(wac);
}
}
if (this.publishContext) {
// 将当前容器放到servlet域中, 可以再创建子容器
String attrName = getServletContextAttributeName();
getServletContext().setAttribute(attrName, wac);
}
return wac;
}






