项目启动之spring篇
在之前终于是把项目跑起来了,也是踩了不少的坑,把bug还原了一遍又一遍,希望能看的更清楚。现在我们跳过tomcat再来看看spring是如何启动的。
项目启动过程之spring篇
1.创建WebApplicationContext
# 首先我们在web.xml的配置了这么一个lisenner
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
# 从源码中找到该类,类中的方法都是调用父类来实现的,如此明显的装饰者模式。
public class ContextLoaderListener extends ContextLoader implements ServletContextListener {
.....
}
# 再看看ContextLoader这个类
public class ContextLoader {
# 这个静态方法只为加载一个ContextLoader.properties文件,不出所料的这个文件跟类在同一个文件夹下。
# 文件中只有一句话 -> org.springframework.web.context.WebApplicationContext=org.springframework.web.context.support.XmlWebApplicationContext
static {
try {
ClassPathResource resource = new ClassPathResource("ContextLoader.properties", ContextLoader.class);
defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);
} catch (IOException var1) {
throw new IllegalStateException("Could not load 'ContextLoader.properties': " + var1.getMessage());
}
currentContextPerThread = new ConcurrentHashMap(1);
}
# 这个方法大致就是如果web.xml没有配置特殊的contextClass则会使用defaultStrategies中指定的类,也就是上面静态方法加载到的配置 XmlWebApplicationContext
protected Class<?> determineContextClass(ServletContext servletContext) {
String contextClassName = servletContext.getInitParameter("contextClass");
if (contextClassName != null) {
try {
return ClassUtils.forName(contextClassName, ClassUtils.getDefaultClassLoader());
} catch (ClassNotFoundException var4) {
throw new ApplicationContextException("Failed to load custom context class [" + contextClassName + "]", var4);
}
} else {
# 如果在web.xml中并未指定contextClass
# 简单写成: contextClassName = "org.springframework.web.context.support.XmlWebApplicationContext"
contextClassName = defaultStrategies.getProperty(WebApplicationContext.class.getName());
try {
return ClassUtils.forName(contextClassName, ContextLoader.class.getClassLoader());
} catch (ClassNotFoundException var5) {
throw new ApplicationContextException("Failed to load default context class [" + contextClassName + "]", var5);
}
}
}
protected WebApplicationContext createWebApplicationContext(ServletContext sc) {
# 将里面代码简单写成:
# return (ConfigurableWebApplicationContext)BeanUtils.instantiateClass(this.determineContextClass(sc));
}
public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) {
....
} else {
.....
# 此时就要开始创建 WebApplicationContext 了
try {
if (this.context == null) {
# 我们假定 this.context 的类型就是 XmlWebApplicationContext
this.context = this.createWebApplicationContext(servletContext);
}
if (this.context instanceof ConfigurableWebApplicationContext) {
ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext)this.context;
if (!cwac.isActive()) { # 刚跑起的项目context一般都没被激活
if (cwac.getParent() == null) {
# 很奇怪,loadParentContext返回的是 return null ??
ApplicationContext parent = this.loadParentContext(servletContext);
cwac.setParent(parent);
}
# 这个方法主要是设置contextId,若没有在web.xml中指定,则会像这个样子:
# org.springframework.web.context.WebApplicationContext:${contextPath}
this.configureAndRefreshWebApplicationContext(cwac, servletContext);
}
}
# 这个才是Lisener的关键,把创建的WebApplicationContext加入到servletContext中。
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
ClassLoader ccl = Thread.currentThread().getContextClassLoader();
if (ccl == ContextLoader.class.getClassLoader()) {
currentContext = this.context;
} else if (ccl != null) {
currentContextPerThread.put(ccl, this.context);
}
return this.context;
.....
}
}
}
# 在XWAC中提供了默认的配置文件位置
public class XmlWebApplicationContext extends AbstractRefreshableWebApplicationContext {
public static final String DEFAULT_CONFIG_LOCATION = "/WEB-INF/applicationContext.xml";
public static final String DEFAULT_CONFIG_LOCATION_PREFIX = "/WEB-INF/";
public static final String DEFAULT_CONFIG_LOCATION_SUFFIX = ".xml";
.....
}
小结一下: tomcat启动时会给配置在web.xml中指定的lisener传递一个事件,让其初始化创建一个WebApplicationContext对象,并将其加入到ServletContext中。而在spring-web中ContextLoaderListener类为我们提供使用默认或自定义两种生成WebApplicationContext对象,需要使用自定义则需要在web.xml中指定contextClass属性,并且创建对应的类。创建好了context之后,下一步便是加载applicationContext中的bean了,暂时也还没有发现如何发起加载bean的过程,继续学习吧。。。
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Centos7已配置环境变量,javac命令执行无效
在centos7中以rpm包安装jdk无需配置环境变量, terminal中输入java -verison及java 命令也是没问题的,但是javac的话就会提示没有此命令 此时我们用yum来装原生的就行了: 使用 yum install java-devel (非管理员账号使用 sudo yum install java-devel命令) 下载安装完毕后,再次输入 javac ,ok了
- 下一篇
循环定时向qq对话框中发送消息
在qq中重复发消息,利用网上的操作代码,自己定义了一个类,用多线程和定时实现对一个qq弹窗循环定时发消息。https://github.com/Wn-Dev/qq_send_messages # 原理是先将需要发送的文本放到剪贴板中,然后将剪贴板内容发送到qq窗口 # 之后模拟按键发送enter键发送消息 import win32gui import win32con import win32clipboard as w import time import threading class SendMessage: to_who ='' msg='' def __init__(self,t,m): self.to_who = t self.msg = m def getText(self): """获取剪贴板文本""" w.OpenClipboard() d = w.GetClipboardData(win32con.CF_UNICODETEXT) w.CloseClipboard() return d def setText(self): """设置剪贴板文本""" w.OpenCl...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
-
Docker使用Oracle官方镜像安装(12C,18C,19C)
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS8编译安装MySQL8.0.19
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
推荐阅读
最新文章
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- Mario游戏-低调大师作品
- CentOS7安装Docker,走上虚拟化容器引擎之路
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- CentOS7,CentOS8安装Elasticsearch6.8.6
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- CentOS6,CentOS7官方镜像安装Oracle11G
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- SpringBoot2配置默认Tomcat设置,开启更多高级功能