Spring 启动分析(1)

2023-05-16

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

Spring MVC 启动记录(1)

1、

090719_giz5_867830.png

默认的初始化就是一个DispatchServlet,这个serlet的初始化过程就是整个spring mvc启动的过程。

1-1、默认初始化父类的init方法

GenericServlet的init 

 public void init(ServletConfig config) throws ServletException {
	this.config = config;
	this.init();
 }

 public void init() throws ServletException {

 }

然后调用子类HttpServletBean复写的init方法

public final void init() throws ServletException {
    if (logger.isDebugEnabled()) {
        logger.debug("Initializing servlet '" + getServletName() + "'");
    }

    // Set bean properties from init parameters.
    try {
        PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);
        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) {
        logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex);
        throw ex;
    }

    // Let subclasses do whatever initialization they like.
    initServletBean();

    if (logger.isDebugEnabled()) {
        logger.debug("Servlet '" + getServletName() + "' configured successfully");
    }
}

 

然后调用initServletBean方法,触发子类FrameworkServlet的initServletBean方法调用

 

protected final void initServletBean() throws ServletException {
		getServletContext().log("Initializing Spring FrameworkServlet '" + getServletName() + "'");
		if (this.logger.isInfoEnabled()) {
			this.logger.info("FrameworkServlet '" + getServletName() + "': initialization started");
		}
		long startTime = System.currentTimeMillis();

		try {
			this.webApplicationContext = initWebApplicationContext();
			initFrameworkServlet();
		}
		catch (ServletException ex) {
			this.logger.error("Context initialization failed", ex);
			throw ex;
		}
		catch (RuntimeException ex) {
			this.logger.error("Context initialization failed", ex);
			throw ex;
		}

		if (this.logger.isInfoEnabled()) {
			long elapsedTime = System.currentTimeMillis() - startTime;
			this.logger.info("FrameworkServlet '" + getServletName() + "': initialization completed in " +
					elapsedTime + " ms");
		}
}

 

其中调用到本地方法initWebApplicationContext方法

protected WebApplicationContext initWebApplicationContext() {
        //获取rootContext
		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.
			onRefresh(wac);
		}
     
		if (this.publishContext) {
			// Publish the context as a servlet context attribute.
			String attrName = getServletContextAttributeName();
			getServletContext().setAttribute(attrName, wac);
			if (this.logger.isDebugEnabled()) {
				this.logger.debug("Published WebApplicationContext of servlet '" + getServletName() +
						"' as ServletContext attribute with name [" + attrName + "]");
			}
		}

		return wac;
	}

 

其中getWebApplicationContext的方法

public static WebApplicationContext getWebApplicationContext(ServletContext sc) {
		return getWebApplicationContext(sc, WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
	}

public static WebApplicationContext getWebApplicationContext(ServletContext sc, String attrName) {
		Assert.notNull(sc, "ServletContext must not be null");
		Object attr = sc.getAttribute(attrName);
		if (attr == null) {
			return null;
		}
		if (attr instanceof RuntimeException) {
			throw (RuntimeException) attr;
		}
		if (attr instanceof Error) {
			throw (Error) attr;
		}
		if (attr instanceof Exception) {
			throw new IllegalStateException((Exception) attr);
		}
		if (!(attr instanceof WebApplicationContext)) {
			throw new IllegalStateException("Context attribute is not of type WebApplicationContext: " + attr);
		}
		return (WebApplicationContext) attr;
	}

findWebApplicationContext方法如下:在之前的基础上按照attributeName找不到则全部遍历

public static WebApplicationContext findWebApplicationContext(ServletContext sc) {
		WebApplicationContext wac = getWebApplicationContext(sc);
		if (wac == null) {
			Enumeration<String> attrNames = sc.getAttributeNames();
			while (attrNames.hasMoreElements()) {
				String attrName = attrNames.nextElement();
				Object attrValue = sc.getAttribute(attrName);
				if (attrValue instanceof WebApplicationContext) {
					if (wac != null) {
						throw new IllegalStateException("No unique WebApplicationContext found: more than one " +
								"DispatcherServlet registered with publishContext=true?");
					}
					wac = (WebApplicationContext) attrValue;
				}
			}
		}
		return wac;
	}

 

没有则进一步创建


FrameworkServlet的方法


protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) {
		return createWebApplicationContext((ApplicationContext) parent);
}

protected WebApplicationContext createWebApplicationContext(ApplicationContext parent) {
		Class<?> contextClass = getContextClass();
        //默认的context class  XmlWebApplicationContext.class;
		if (this.logger.isDebugEnabled()) {
			this.logger.debug("Servlet with name '" + getServletName() +
					"' will try to create custom WebApplicationContext context of class '" +
					contextClass.getName() + "'" + ", using parent context [" + parent + "]");
		}
		if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {
			throw new ApplicationContextException(
					"Fatal initialization error in servlet with name '" + getServletName() +
					"': custom WebApplicationContext class [" + contextClass.getName() +
					"] is not of type ConfigurableWebApplicationContext");
		}
		ConfigurableWebApplicationContext wac =
				(ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);

		wac.setEnvironment(getEnvironment());
		wac.setParent(parent);
		wac.setConfigLocation(getContextConfigLocation());

		configureAndRefreshWebApplicationContext(wac);

		return wac;
	}

 

其中获取contextClass是由FrameworkServlet的本地属性定义

public static final Class<?> DEFAULT_CONTEXT_CLASS = XmlWebApplicationContext.class;

判断完类型后初始化 XmlWebApplicationContext.class这个类

调用BeanUtils的instanceClass方法


BeanUtils
//检查是否为接口或者为空,获取构造器反射类进一步调用
public static <T> T instantiateClass(Class<T> clazz) throws BeanInstantiationException {
		Assert.notNull(clazz, "Class must not be null");
		if (clazz.isInterface()) {
			throw new BeanInstantiationException(clazz, "Specified class is an interface");
		}
		try {
			return instantiateClass(clazz.getDeclaredConstructor());
		}
		catch (NoSuchMethodException ex) {
			throw new BeanInstantiationException(clazz, "No default constructor found", ex);
		}
}
//暴力破解私有构造,调用Constructor实例化一个实例
public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {
		Assert.notNull(ctor, "Constructor must not be null");
		try {
			ReflectionUtils.makeAccessible(ctor);
			return ctor.newInstance(args);
		}
		catch (InstantiationException ex) {
			throw new BeanInstantiationException(ctor.getDeclaringClass(),
					"Is it an abstract class?", ex);
		}
		catch (IllegalAccessException ex) {
			throw new BeanInstantiationException(ctor.getDeclaringClass(),
					"Is the constructor accessible?", ex);
		}
		catch (IllegalArgumentException ex) {
			throw new BeanInstantiationException(ctor.getDeclaringClass(),
					"Illegal arguments for constructor", ex);
		}
		catch (InvocationTargetException ex) {
			throw new BeanInstantiationException(ctor.getDeclaringClass(),
					"Constructor threw exception", ex.getTargetException());
		}
	}

直接 获取ServletContext 中的getAttribute调用是否有初始化过的ApplicationContext对象

 

进而初始化XmlWebApplicationContext类

该类图如下

105815_atJo_867830.png

 

只有三个默认属性,集成如下,顾初始化所以的父类构造器,继承如下

110151_3ZZh_867830.png
初始化web xml中的severlet配置到spring的beanwrapper中

 

 

 

 

转载于:https://my.oschina.net/u/867830/blog/822745

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring 启动分析(1) 的相关文章

  • linux脚本打开文件任意行,shell脚本语言(超全超详细)

    shell脚本语言 1 shell的概述 2 脚本的调用形式 打开终端时系统自动调用 xff1a etc profile 或 bashrc 3 shell语法初识 3 1 定义以开头 xff1a bin bash 3 2 单个 34 34
  • awk系列:如何使用awk的特殊模式 BEGIN 和 END

    在 awk 系列的第八节 xff0c 我们介绍了一些强大的 awk 命令功能 xff0c 它们是变量 数字表达式和赋值运算符 本节我们将学习更多的 awk 功能 xff0c 即 awk 的特殊模式 xff1a BEGIN 和 END 随着我
  • 上云有风险 公有云选型小心进坑

    本文讲的是上云有风险 公有云选型小心进坑 IT168 云计算 市场商业的运作规则就是大鱼吃小鱼小鱼吃虾米 xff0c 适者生存 在公有云领域 xff0c 如果你没有实力长时间支撑一个企业运营微利甚至不盈利 xff0c 那么云平台倒下一定是必
  • RabbitMQ消息可靠性分析

    欢迎支持笔者新书 xff1a RabbitMQ实战指南 以及关注微信公众号 xff1a 朱小厮的博客 Introduction 有很多人问过我这么一类问题 xff1a RabbitMQ如何确保消息可靠 xff1f 很多时候 xff0c 笔者
  • debian关闭图形界面_Debian Linux进入不了图形界面的折腾

    首先我的操作系统是Debian Linux xff0c 我Debian用的是Xfce桌面环境 xff0c 昨天我用了命令apt get install gnome 安装了一堆软件之后重启 xff0c 就进入不了图形界面了 xff0c 只能进
  • 计算机网络操作系统的主要功能和类型,操作系统的五大管理功能和四大分类

    操作系统是管理计算机硬件资源 xff0c 控制其他程序运行并为用户提供交互操作界面的系统软件的集合 操作系统是计算机系统的关键组成部分 xff0c 负责管理与配置内存 决定系统资源供需的优先次序 控制输入与输出设备 操作网络与管理文件系统等
  • 使用Formik轻松开发更高质量的React表单(二)使用指南

    一个基本的例子 设想你要开发一个可以编辑用户数据的表单 不过 xff0c 你的用户API端使用了具有类似下面的嵌套对象表达 xff1a id string email string social facebook string twitte
  • Media Foundation基本概念

    Media Foundation Media Foundation xff08 简称MF xff09 是微软用来替换DirectShow的视频API xff0c 从Vista开始支持 xff0c 直到现在的Windows 8 xff0c W
  • 算法公式 - 图形化

    在定制 数学公式的时候 可能 希望有个直观的 展现 http www wolframalpha com 我们前一段时间用到的 推荐分值 90 天 递减公式 xff0c 如果这东西早发现 公式就不会错了 xff01 目前我们递减的公式 y 6
  • windows平台使用SecureCRT+Xming实现图形界面来执行linux平台的一些图形程序

    需求分析 xff1a windows平台下使用ssh远程连接linux服务器 xff0c 实现图形界面来执行linux平台的一些程序 xff0c 如system config kickstart xeyes 等 实验环境 xff1a 服务器
  • 上线:准备和部署软件包时开发和运维的角色

    按照发布流程正确的部署软件 二进制代码和与之相关的配置文件 到你的开发 测试 验收或产品环境 xff08 DTAP xff09 是一项复杂的任务 xff0c 涉及到众多部门和团队 不幸的是 xff0c 在许多组织中这项关键的流程还是费时并容
  • TortoiseGit安装与配置

    2019独角兽企业重金招聘Python工程师标准 gt gt gt TortoiseGit 简称 tgit 中文名海龟Git 海龟Git只支持神器 Windows 系统 有一个前辈海龟SVN TortoiseSVN和TortoiseGit都
  • 在CentOS 7中Samba服务安装和配置

    这篇指南介绍了如何在CentOS7中配置匿名和安全的Samba服务器 Samba是一个开源 自由软件套件 xff0c 提供无缝的文件和打印服务SMB CIFS客户端 Samba是免费的 xff0c 不像其他的SMB CIFS的实现着 Sam
  • 如何清除团队中的“害群之马”?(下篇)

    阅读更多系列文章请访问我的GitHub博客 这篇文章来自于一位同事面试时被问到的一个问题 xff1a 如果团队内有老员工 xff0c 能力不强又喜欢偷懒 xff0c 怎么办 xff1f 对于这类问题 xff0c 最简单的回答就是 xff1a
  • oracle 备份失败 RMAN-03002,RMAN-00569,RMAN-00571等处理方法

    备份失败 1 备份失败信息 xff1a 39 52 备份 200 3 oracle 数据 开始执行 11 39 54 NICEGAIN SW741B 开始分析备份数据源 xff0c 请稍候 11 39 54 Oracle Database
  • KVM 开启嵌套虚拟化

    问题 在 CentOS KVM 上启动虚拟机来部署 OpenStack 测试环境 xff0c 在启动具有 CPU 绑定 NUMA 亲和的虚拟机时触发错误 xff1a libvirtError Requested operation is n
  • VNC指定用户屏幕号登录(Oracle安装时使用)

    由于oracle在安装的过程中需要从oracle切换到root用户 xff0c 为了在安装的时候 xff0c 可以远程安装 xff0c 故对VNC进行配置 vim etc sysconfig vncservers定义root的屏幕号为1 o
  • ubuntu 18.04屏幕共享

    2019独角兽企业重金招聘Python工程师标准 gt gt gt windows7系统通过连接ubuntu 18 04屏幕共享 xff0c 来访问Ubuntu桌面 1 安装 xff1a sudo apt install xrdp 2 编辑
  • Git:分支管理

    本文目录 1 使用方法 1 1 常规开发 1 2 热修复 1 3 净化Test分支 2 冲突解决 3 分支说明 3 1 master分支 3 2 release分支 3 3 test分支 3 4 feature分支 3 5 hotfix分支
  • [转载]打造自己喜欢的Linux桌面----archlinux

    原文地址 xff1a 打造自己喜欢的Linux桌面 archlinux 作者 xff1a 三尺椴 打造自己的Linux桌面 Archlinux 2011 01 16 文 s cd xff08 常用桌面组合 Archlinux 43 fvwm

随机推荐

  • 操作日志工具类

    package com util import java util Date import java util UUID import javax servlet http HttpServletRequest import org spr
  • 其他窗体赋值给comboBox实现值的回显,并使赋的值处于选中状态(根据text获取selectedindex)...

    Form1 发货单位的这个下拉框comboBox1已经绑定数据库test表的name字段 xff0c 里面有很多单位名称 比如有 xff1a 甲公司 乙公司 1 Form1的comboBox1首先绑定数据库的数据表test using SQ
  • 树莓派之OLED12864视频播放—BadApple

    代码地址如下 xff1a http www demodashi com demo 13218 html 概述 本篇教程讲述了使用树莓派驱动OLED12864液晶屏 并在液晶屏上播放动画和视频 硬件平台 树莓派一台 RaspberryPi 2
  • 帮你解决无法安装ia32-libs 的问题

    在安装安装wpsforlinux等软件时 xff0c 我们要经常要运行 代码 sudo apt get install ia32 libs 问题 xff1a 解决办法 xff1a 一 在终端运行 sudo apt get install g
  • 爬虫带你了解一下Golang的市场行情

    了解一下Golang的市场行情 项目地址 xff1a https github com go crawler 如果对你有所帮助 xff0c 欢迎 Star xff0c 给文章来波赞 xff0c 这样可以让更多的人看见 目标 在工作中 Gol
  • C语言如何分离一个数的高低位,如何将2个字节变成一个字节

    关于这个概念 xff0c 是我从工作中学习的 xff0c 虽然在读书的时候就应该要掌握 xff0c 但是在开发中 xff0c 这项技能尤其重要 我是做嵌入式开发的 xff0c 在嵌入式开发过程中 xff0c 如何对数据操作必然是不可缺少的问
  • 你要的免费Proxy资源全在这里了

    地址 xff1a github com derekhe Pro 介绍 在 爬虫实战 xff1a 从数据到产品 一书中 xff0c 我讲到了一个基于ProxyBroker的代理池 经过我的长时间的实践 xff0c 这个代理池用起来非常的方便和
  • 短视频App源码:如何搭建短视频社区

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 短视频App源码 xff1a 如何搭建短视频社区 随着国内移动互联网的发展 xff0c 中国的移动互联网时代已经来临 xff0c 以快手 抖音为主的短视频平台迅速火热起来
  • mysql 百万级数据的模糊查询 优化 笔记

    最近老大给了一个需求 xff0c 是要写一个姓名的模糊查询 问题很简单 xff0c 难度在于这张表有将近500W条数据 如果要做中文的模糊查询 xff0c 效率简直惨不忍睹 网上查了一下资料 xff0c 发现全文索引挺符合我的需要的 结果
  • 如何在Ubuntu 18.04上创建启用了Sudo的新用户[快速入门]

    介绍 Introduction The sudo command provides a mechanism for granting administrator privileges ordinarily only available to
  • Sql语句批量更新数据(多表关联)

    最近在项目中遇到一个问题 xff0c 原来设计的功能是不需要一个特定的字段值depid的 xff0c 但是新的功能需要根据depid来展现 xff0c 于是出现了这样一个问题 xff0c 新增加的数据都有正确的depid 而原来的大量的数据
  • Matlab M文件“程序块”注释方法

    方法一 xff1a 注释语句的快捷键是Ctrl 43 R 取消注释的快捷键是Ctrl 43 T 并且支持一次注释 xff08 或者取消注释 xff09 多行语句 选定要注释 xff08 或者取消注释 xff09 的那些语句 xff0c 然后
  • 如何开发高性能低成本的网站之技术选择

    每个企业都是慢慢发展起来的 xff0c 在起步阶段成本是一个不得不考虑的重大问题 直接入正题 xff1a 前台框架 ASP NET MVC 43 Jquery 43 Json 43 Flash ASP NET MVC 高性能速度快 xff0
  • 密码学题库

    参考题库 一 选择题 1 第一个实用的 迄今为止应用最广的公钥密码体制是 A A RSA B Elgamal C ECC D NTRU 2 一个密码系统至少由明文 密文 加密算法和解密算法 密钥五部分组成 xff0c 而其安全性是由 xff
  • 【linux】linux 下 shell命令 执行结果赋值给变量【两种方式】

    方法1 xff1a 通用方法 使用Tab键上面的反引号 例子如下 xff1a find命令 模糊查询在 apps swapping目录下 查找 文件名中包含swapping并且以 jar结尾的文件 使用反引号 引住命令 xff0c 然后使用
  • Octet 和 Byte 的区别

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 关于程序的文章中 Octet 和 Byte是常见的词汇 xff0c 他们都表示8 bit 在读RFC或网络设备文档时 xff0c 经常见到Octet这量词来指代8位 xff
  • 云计算的弹性

    云计算最大的优势就在于弹性 目前 xff0c 阿里云已拥有在数分钟内开出一家中型互联网公司所需要的IT资源的能力 xff0c 这就能够保证大部分企业在云上所构建的业务都能够承受巨大的业务量压力 计算弹性 纵向的弹性 xff0c 即单个服务器
  • LACP 详解

    一 LACP简介 1 LACP协议简介 基于 IEEE802 3ad 标准的LACP xff08 Link Aggregation Control Protocol xff0c 链路汇聚控 制协议 xff09 是一种实现链路动态汇聚与解汇聚
  • 串口发送数据

    关于串口发送数据 自己以前呢是这样 void Usart Out Char unsigned char c uint32 t cnt while cnt USART SendData USART1 c 43 43 while USART G
  • Spring 启动分析(1)

    2019独角兽企业重金招聘Python工程师标准 gt gt gt Spring MVC 启动记录 xff08 1 xff09 1 默认的初始化就是一个DispatchServlet xff0c 这个serlet的初始化过程就是整个spri