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. javascript学习笔记(六):对象、内置对象

    创建对象 对象属性赋值的方式 <!DOCTYPE html> <html> <head lang="en"> <meta chaset=& ...

  2. Jmeter(十九) Md5加密操作之-------BeanShell PreProcessor(转载)

    转载自 http://www.cnblogs.com/yangxia-test 背景: 有一些登录会做一些md5校验,通过jmeter的BeanShell可以解决MD5加密情况. 1.首先需要一个解码 ...

  3. Pandas基本功能之选取索引和过滤

    索引.选取和过滤 大部分的查询用法 类型 说明 obj[val] 选取DataFrame的单个列或一组列 obj.ix[val] 选取DataFrame的单个行或一组行 obj.ix[:,val] 选 ...

  4. WINDOWS防火墙开启后Ping不通

    WINDOWS系统由于安全考虑,当开启防火墙时,默认不允许外主机对其进行ping功能,即别的电脑ping不通本机.别的主机ping不通本机是因为本机的防火墙关闭了ICMP回显功能,只要把这回显功能打开 ...

  5. 新版本PHP使用更方便了

    $hostname_conn = "";$database_conn = "";$username_conn = "root";$passw ...

  6. 纯css3棋盘图案背景以及45度斜纹背景

    css代码  .stripes {     height: 250px;     width: 375px;     float: left;          margin: 10px;      ...

  7. CUDA 编程的基本模式

    reproduced from: http://www.cnblogs.com/muchen/p/6306747.html 前言 本文将介绍 CUDA 编程的基本模式,所有 CUDA 程序都基于此模式 ...

  8. HDU-1257.最少拦截系统(基础DP)

    本题大意:给出n和n个整数,让你求出其中不上升子序列的个数. 本题思路:用dp[ i ]保存第i个防御系统攻击的最低的导弹,遍历数组,遇到更低的导弹则更新最小值,否则新加一个系统用来防御,并且更新最小 ...

  9. [Java学习]常用类-包装类型

    八种基本类型对应的包装类 Java中的数据类型由八种基本类型,以及引用类型组成. byte short int long float double boolbean char Object 为了方便, ...

  10. django分页的东西, 不详细, 但是也足够了。

    视图函数中的代码 from django.shortcuts import render, HttpResponse, redirect import json from django.core.pa ...