Spring MVC中DispatchServlet原理讲解(一)

在研究DispatchServlet之前必须先要知道DispatchServlet是在何时被注入到servletContext中的。

在上一篇中讲过,启动Tomcat服务是通过TomcatServletWebServerFactory类中的getWebServer方法来实现的,而getWebServer的参数是通过ServletWebServerApplicationContext类中的getSelfInitializer方法来实现的,下面是getSelfInitializer的源码:

private ServletContextInitializer getSelfInitializer() {
    return this::selfInitialize;
}

通过查看类图可以得知ServletContextInitializer类是一个继承了函数式接口的类

再来看selfInitialize函数的源码

private void selfInitialize(ServletContext servletContext) throws ServletException {
	this.prepareWebApplicationContext(servletContext);
	this.registerApplicationScope(servletContext);
	WebApplicationContextUtils.registerEnvironmentBeans(this.getBeanFactory(), servletContext);
	Iterator var2 = this.getServletContextInitializerBeans().iterator();

	while(var2.hasNext()) {
		ServletContextInitializer beans = (ServletContextInitializer)var2.next();
        // 主要方法
		beans.onStartup(servletContext);
	}

}

在运行的时候,将端点打在beans.onStartup()这个方法上时,发现beans是一些Filters和一些对应的RegistionBean,这些都是用于对请求进行处理的对象,其中就包括一个DispatchServletRegistionBean对象,该对象是用于将DispatchServlet对象注入到servletContext上下文中。

通过查看类图得知DispatchServletRegistionBean类为RegistrationBean的子类

 DispatchServletRegistionBean类中没有onStartup方法,实际上执行的还是RegistrationBean类中的onStartup方法。RegistrationBean类中的onStartup方法源码如下所示

public final void onStartup(ServletContext servletContext) throws ServletException {
	String description = this.getDescription();
	if (!this.isEnabled()) {
		logger.info(StringUtils.capitalize(description) + " was not registered (disabled)");
	} else {
		this.register(description, servletContext);
	}
}

其中getDescription方法的源码很简单,就是获取一个字符串对象,最终调用的是ServletRegistrationBean类中的getDescription方法,源码如下

protected String getDescription() {
	Assert.notNull(this.servlet, "Servlet must not be null");
	return "servlet " + this.getServletName();
}

主要的注入方法为下面的redister方法,DispatchServletRegistionBean类中没有redister方法,实际上执行的是DynamicRegistrationBean类中的redister方法,源码如下

protected final void register(String description, ServletContext servletContext) {
	D registration = this.addRegistration(description, servletContext);
	if (registration == null) {
		logger.info(StringUtils.capitalize(description) + " was not registered (possibly already registered?)");
	} else {
		this.configure(registration);
	}
}

然后进入ServletRegistrationBean的addRegistration函数

protected Dynamic addRegistration(String description, ServletContext servletContext) {
	String name = this.getServletName();
	return servletContext.addServlet(name, this.servlet);
}

从这个函数中可以看出,前面的DispatchServletRegistionBean对象已经被加入到servletContext的上下。从DispatchServletRegistionBean的构造函数可以看出,DispatchServletRegistionBean的构造函数需要传入一个DispatchServlet对象,而这个DispatchServlet对象在DispatchServletRegistionBean的父类ServletRegistrationBean中作为一个成员变量,因此DispatchServletRegistionBean注入到servletContext也代表着DispatchServlet的注入成功。

public DispatcherServletRegistrationBean(DispatcherServlet servlet, String path) {
	super(servlet, new String[0]);
	Assert.notNull(path, "Path must not be null");
	this.path = path;
	super.addUrlMappings(new String[]{this.getServletUrlMapping()});
}

下一节再来看一看DispatchServlet类的源码,了解DispatchServlet是如何运作的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值