Spring Environment(三)生命周期

Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html)

Spring Environment 属性配置管理系列文章:

  1. Spring Environment(一)API 介绍
  2. Spring Environment(二)源码分析
  3. Spring Environment(三)生命周期

一、Environment 初始化

每个 ApplicationContext 容器初始化时都会执行 ApplicationContext#refresh() 方法,这个方法的第一步就是 prepareRefresh 方法。

protected void prepareRefresh() {
// 1. 初始化一个 Environment 并注入数据源
initPropertySources();
// 2. 对必要的属性进行校验
getEnvironment().validateRequiredProperties();
} @Override
protected void initPropertySources() {
// 1. 获取 Environment 实例
ConfigurableEnvironment env = getEnvironment();
// 2. 如果是 WEB 环境需要注入 ServletContext 和 servletConfig 数据源
if (env instanceof ConfigurableWebEnvironment) {
((ConfigurableWebEnvironment) env).initPropertySources(this.servletContext, this.servletConfig);
}
}

AbstractApplicationContext#getEnvironment() 方法默认是创建一个 StandardEnvironment,只注入了 OS 和 JVM 相关的属性。

@Override
public ConfigurableEnvironment getEnvironment() {
if (this.environment == null) {
this.environment = createEnvironment();
}
return this.environment;
}
protected ConfigurableEnvironment createEnvironment() {
return new StandardEnvironment();
}

二、WEB 环境下 Environment 初始化

WEB 启动时会初始化两个容器,一个是 ROOT WebApplicationContext;一个是 Servlet WebApplicationContext。这两个容器分别是在启动 ContextLoaderListener 和 DispatcherServlet 时初始化的。

2.1 ROOT WebApplicationContext

(1) XmlWebApplicationContext

ROOT WebApplicationContext 默认实现类是 XmlWebApplicationContext,是在和 ContextLoader 同级目录的 ContextLoader.properties 文件中配置的。获取其实现类方法如下:

protected Class<?> determineContextClass(ServletContext servletContext) {
String contextClassName = servletContext.getInitParameter(CONTEXT_CLASS_PARAM);
if (contextClassName != null) {
return ClassUtils.forName(contextClassName, ClassUtils.getDefaultClassLoader());
} else {
contextClassName = defaultStrategies.getProperty(WebApplicationContext.class.getName());
return ClassUtils.forName(contextClassName, ContextLoader.class.getClassLoader());
}
}

XmlWebApplicationContext 的父类 AbstractRefreshableWebApplicationContext 重写了 createEnvironment 方法,返回 StandardServletEnvironment 对象。

@Override
protected ConfigurableEnvironment createEnvironment() {
return new StandardServletEnvironment();
}

Spring 调用 refresh 时就会执行 initPropertySources 方法将 ServletContext、ServletConfig 属性注入到 Environment 中,但为了保证 refresh 之前就可以通过 Environment 获取这些属性会提前注入。

(2) 提前执行 initPropertySources

public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
if (this.context == null) {
this.context = createWebApplicationContext(servletContext);
}
if (this.context instanceof ConfigurableWebApplicationContext) {
ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context;
if (!cwac.isActive()) {
// 1. 配置父容器,如果有
if (cwac.getParent() == null) {
ApplicationContext parent = loadParentContext(servletContext);
cwac.setParent(parent);
}
// 2. 配置并启动容器 refresh
configureAndRefreshWebApplicationContext(cwac, servletContext);
}
}
} protected void configureAndRefreshWebApplicationContext(
ConfigurableWebApplicationContext wac, ServletContext sc) {
// 省略... // #refresh 调用之前将 ServletContext 注入到 Environment 中,这样就可以提前使用
ConfigurableEnvironment env = wac.getEnvironment();
if (env instanceof ConfigurableWebEnvironment) {
((ConfigurableWebEnvironment) env).initPropertySources(sc, null);
} customizeContext(sc, wac);
wac.refresh();
}

2.2 Servlet WebApplicationContext

DispatcherServlet 继承自 HttpServlet,初始化时会执行对应的 init() 方法,也会创建一个 WebApplicationContext。其默认的实现类也是 XmlWebApplicationContext。

(1) 创建 WebApplicationContext

protected WebApplicationContext initWebApplicationContext() {
WebApplicationContext rootContext =
WebApplicationContextUtils.getWebApplicationContext(getServletContext());
WebApplicationContext wac = null;
// 省略...
if (wac == null) {
// 创建 WebApplicationContext
wac = createWebApplicationContext(rootContext);
}
if (!this.refreshEventReceived) {
synchronized (this.onRefreshMonitor) {
onRefresh(wac);
}
}
return wac;
} protected WebApplicationContext createWebApplicationContext(@Nullable ApplicationContext parent) {
Class<?> contextClass = getContextClass();
ConfigurableWebApplicationContext wac =
(ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
// 设置 Environment 环境变量
wac.setEnvironment(getEnvironment());
wac.setParent(parent);
String configLocation = getContextConfigLocation();
if (configLocation != null) {
wac.setConfigLocation(configLocation);
}
configureAndRefreshWebApplicationContext(wac);
return wac;
}

(2) 提前执行 initPropertySources

和 ROOT WebApplicationContext 类似,也会提前将 ServletContext 和 ServletConfig 提前注入到 Environment 变量中。

protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac) {
ConfigurableEnvironment env = wac.getEnvironment();
if (env instanceof ConfigurableWebEnvironment) {
((ConfigurableWebEnvironment) env).initPropertySources(getServletContext(), getServletConfig());
} postProcessWebApplicationContext(wac);
applyInitializers(wac);
wac.refresh();
}

每天用心记录一点点。内容也许不重要,但习惯很重要!

Spring Environment(三)生命周期的更多相关文章

  1. Spring(三)--Spring bean的生命周期

    Spring bean的生命周期 ApplicationContext Bean生命周期流程 1.需要的实体类 ackage com.xdf.bean; import org.springframew ...

  2. Spring Bean的生命周期(非常详细)

    Spring作为当前Java最流行.最强大的轻量级框架,受到了程序员的热烈欢迎.准确的了解Spring Bean的生命周期是非常必要的.我们通常使用ApplicationContext作为Spring ...

  3. Spring Bean的生命周期详解(转)

    Spring作为当前Java最流行.最强大的轻量级框架,受到了程序员的热烈欢迎.准确的了解Spring Bean的生命周期是非常必要的.我们通常使用ApplicationContext作为Spring ...

  4. Spring动态代理及Spring Bean的生命周期

    数组添加值 public class DiTest { /** * 数组 */ private String [] arrays; /** * List:集合 */ private List<I ...

  5. 第37讲 谈谈Spring Bean的生命周期和作用域

    在企业应用软件开发中,Java 是毫无争议的主流语言,开放的 Java EE 规范和强大的开源框架功不可没,其中 Spring 毫无疑问已经成为企业软件开发的事实标准之一.今天这一讲,我将补充 Spr ...

  6. Spring Bean的生命周期、Spring MVC的工作流程、IOC,AOP

    1.Spring Bean的生命周期? (1)构造方法实例化bean. (2)构造方法设置对象属性. (3)是否实现aware接口,三种接口(BeanNameAware,BeanFactoryAwar ...

  7. 谈谈Spring bean的生命周期(一)

    简介 本片文章主要讲Spring IOC容器中 bean 的生命周期 Spring bean 生命周期 Spring 中bean的声明周期 可以分为如下4个阶段: 实例化阶段--Instantiati ...

  8. Spring应用上下文生命周期

    Spring应用上下文生命周期整体分成四个阶段 ConfigurableApplicationContext#refresh,加载或者刷新持久化配置 ConfigurableApplicationCo ...

  9. spring bean的生命周期

    掌握好spring bean的生命周期,对spring的扩展大有帮助.  spring bean的生命周期(推荐看)  spring bean的生命周期

  10. Spring Bean的生命周期,《Spring 实战》书中的官方说法

    连着两天的面试 ,都问到了 Spring 的Bean的生命周期,其中还包括 昨晚一波阿里的电话面试.这里找到了Spring 实战中的官方说法.希望各位要面试的小伙伴记住,以后有可能,或者是有时间 去看 ...

随机推荐

  1. HDU 6351 Naive Operations(线段树)

    题目: http://acm.hdu.edu.cn/showproblem.php?pid=6315 Naive Operations Time Limit: 6000/3000 MS (Java/O ...

  2. div 光标处插入内容

    var Manager = { insertHtml: function(html, type) { var lastMemo = document.getElementById("memo ...

  3. Eureka 剔除失效服务

    Spring Cloud 版本: Dalston.SR5 服务端配置: # 关闭保护机制 eureka.server.enable-self-preservation=false #剔除失效服务间隔 ...

  4. heat创建stack

    1.使用模板创建虚拟机 heat_template_version: 2018-09-04 description: Simple template to deploy a virtual machi ...

  5. 第八篇:Jmeter的分布式测试

    一: 由于Jmeter本身的瓶颈,当模拟数以千计的用户并发的时候,使用单台机器会有些力不从心,甚至还会引起Java内存溢出的错误,要解决这个问题,就要使用分布式测试,运行多台机器,也就是所谓的Agen ...

  6. WAS 常见报错

    1) An error occurred while deleting the server. ADMG0011E: An unexpected exception occurred com.ibm. ...

  7. TOJ 3973 Maze Again && TOJ 3128 简单版贪吃蛇

    TOJ3973传送门:http://acm.tzc.edu.cn/acmhome/problemdetail.do?&method=showdetail&id=3973 时间限制(普通 ...

  8. 模拟点击事件在alert前不起作用

    本来想在ajax提交前点击一下模态框,直到返回处理之前都显示正在保存,发现如标题的现象,几经折腾没找到解决办法,发现可能是 alert线程阻塞(冒泡)引起的,也没找到解决办法,于是借助第三方插件lay ...

  9. java 基础之--类加载器的过程

    先来段代码,大家瞧瞧运行pritln的结果是什么?(认真想一想哦

  10. LRU缓存原理

    LRU(Least Recently Used)  LRU是近期最少使用的算法,它的核心思想是当缓存满时,会优先淘汰那些近期最少使用的缓存对象. 采用LRU算法的缓存有两种:LrhCache和DisL ...