栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

SpringMvc 源码分析 (SpringMvc 启动流程和原理解析) (二)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

SpringMvc 源码分析 (SpringMvc 启动流程和原理解析) (二)

这里的SpringMvc是基于注解版的, 在Servlet3.0之后注解版为主要的实现方式。

public class AppStarter implements WebApplicationInitializer {
    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        // Ioc 容器
        AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
        context.register(SpringMVCConfig.class);

        // IOC未启动
        // 配置DispatchServlet: FrameworkServlet: initServletBean()
        DispatcherServlet servlet = new DispatcherServlet(context);
        // servlet加入到servletContext后,Tomcat会对DispatcherServlet初始化
        ServletRegistration.Dynamic registration = servletContext.addServlet("servlet", servlet);
        registration.setLoadOnStartup(1);
        registration.addMapping("/");

    }
}

文章目录
      • 1.Spi机制处理
      • 2.调用onStarterup方法
      • 3.DispatcherServlet类分析
      • 4.web容器的准备阶段
      • 5.Question

1.Spi机制处理



Servlet的规范ServletContainerInitializer的实现类SpringServletContainerInitializer上面的注解@HandlesTypes代表着WebApplicationInitializer这个接口的实现都是来自Spi机制的。


于是加载了所有实现WebApplicationInitializer的接口的类

2.调用onStarterup方法

于是找到了AppStarter这个主类, 调用WebApplicationInitializer的onStartup方法。


这个方法:

  1. 实例化一个ioc容器, 但是只是一个空的容器
  2. 实例化DispatcherServlet, 并在其中传入ioc容器, 并注册到了ServletContext中, 就是注册到了Tomcat中

这里因为DipatcherServlet是一个Servlet, 所以会遵循Servlet规范:

  1. Servlet 创建对象
  2. Servlet 调用init初始化
  3. 每次请求调用service方法进行处理
  4. tomcat停止的时候调用destroy方法

3.DispatcherServlet类分析


根据DispatcherServlet -> FrameworkServlet -> HttpServletBean -> HttpServlet -> GenericServlet -> Servlet

这里的HttpServlet -> GenericServlet -> Servlet 为Servlet包下的
DispatcherServlet -> FrameworkServlet -> HttpServletBean 是Spring包下的

Servlet.service()
-> GenericService.service()
-> HttpServlet.service():doGet/Post
-> HttpServletBean
-> FrameworkServlet.processRequest(): 统一处理请求的入口
-> DispatcherServlet.doService()
下一篇进行介绍

HttpServletBean 会有一个强大的init方法:

这里的initServletBean为模板方法模式, 为子类提供扩展

FrameworkServlet#initServletBean()

initFrameworkServlet为模板方法模式, 为子类提供扩展

4.web容器的准备阶段

	protected WebApplicationContext initWebApplicationContext() {
		WebApplicationContext rootContext =
				WebApplicationContextUtils.getWebApplicationContext(getServletContext());
		WebApplicationContext wac = null;

		if (this.webApplicationContext != null) {
			// A context instance was injected at construction time -> use it
			wac = this.webApplicationContext;
			if (wac instanceof ConfigurableWebApplicationContext) {
				ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac;
				if (!cwac.isActive()) {
					// The context has not yet been refreshed -> provide services such as
					// setting the parent context, setting the application context id, etc
					if (cwac.getParent() == null) {
						// The context instance was injected without an explicit parent -> set
						// the root application context (if any; may be null) as the parent
						cwac.setParent(rootContext);
					}
					configureAndRefreshWebApplicationContext(cwac);
				}
			}
		}
		if (wac == null) {
			// No context instance was injected at construction time -> see if one
			// has been registered in the servlet context. If one exists, it is assumed
			// that the parent context (if any) has already been set and that the
			// user has performed any initialization such as setting the context id
			wac = findWebApplicationContext();
		}
		if (wac == null) {
			// No context instance is defined for this servlet -> create a local one
			wac = createWebApplicationContext(rootContext);
		}

		if (!this.refreshEventReceived) {
			// Either the context is not a ConfigurableApplicationContext with refresh
			// support or the context injected at construction time had already been
			// refreshed -> trigger initial onRefresh manually here.
			synchronized (this.onRefreshMonitor) {
				onRefresh(wac);
			}
		}

		if (this.publishContext) {
			// Publish the context as a servlet context attribute.
			String attrName = getServletContextAttributeName();
			getServletContext().setAttribute(attrName, wac);
		}

		return wac;
	}

这个方法中提供了父子容器的概念。
这个方法中有onRefresh方法, 是spring提供的一个模板方法的扩展方法

这个onRefresh()方法提供了根据不同的策略来初始化容器中的组件

这里设计到了web容器的9大组件。下一篇进行介绍。

5.Question

1.ioc容器是什么时候初始化的

RA:
1.Tomcat启动的时候, 会创建每一个Servlet对象
2.Tomcat会给每一个DispatcherServlet创建对象
3.当DispatcherServlet初始化之后 ioc容器也会初始化

2.9大组件什么时候初始化的

RA:
利用的是Spring的事件驱动初始化的。
1.tomcat启动
2.触发DS初始化
3.初始化全部结束后, 容器会发送事件, 初始化9大组件

3.IOC容器和web容器是什么时候初始化的

RA:
IOC容器为tomcat启动后, 监听器钩子启动IOC容器, 实例化: 应用启动监听器回调。
web容器为tomcat调用DS的初始化init(), 进行初始化: DS初始化init()回调。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/865653.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号