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. WINDOW 2008多人访问设置

    gpedit.msc,在组策略中对位于“计算机配置->策略->管理模板->Windows 组件->远程桌面服务->远程桌面会话主机->连接”中,限制连接数量中进行配 ...

  2. ettercap的使用

    ettercap -i eth0 -T -M arp:remote -q /<网关地址>// /<目标地址>// arp:remote ,表示双向 使用图形化界面 etterc ...

  3. Unable to compile class for JSP

    https://www.cnblogs.com/mthoutai/p/7136304.html 错误提示: The return type is incompatible with JspSource ...

  4. html的textarea默认文案实现换行

    问题:textarea默认文案,想使用换行展示 但是使用/r/n</br>之类的都无效   解决方法: 使用下面字符实现换行   <textarea >第一行内容 第二行内容& ...

  5. 基于xtrabackup GDIT方式不锁库作主从同步(主主同步同理,反向及可)

    1.安装数据同步工具 注:xtrabackup 在数据恢复的时候比mysqldump要快很多,特别是大数据库的时候,但网络传输的内容要多,压缩需要占用时间. yum install https://w ...

  6. postman使用方法

    Postman sending requests 打开Postman,可以看到界面分成左右两个部分,右边是我们后头要讲的collection,左边是现在要讲的request builder.在requ ...

  7. 第二章 向量(a)接口与实现

  8. numpy的使用数组的创建2

    随机创建了长度为十的数组 获得十以类的随机整数 快速获取数组2乘3维的数组 生成20个1到10之间的数组 通过reshape 将这些数变成二位数组 shape这个方法可以查看数组中的元素是几行几列的

  9. 8.16 val()和html()的问题

    今天在做关闭模态框重置表单时,关闭模态框后输入框里的值还是在,不知道怎么回事? 感谢wd啦,原来我在初始化这个输入框的时候就写错了,输入框写值的时候用的是val(),而我和上面的div一样,用的是ht ...

  10. Android的事件分发机制

    public boolean dispatchTouchEvent(MotionEvent event) 通过方法名我们不难猜测,它就是事件分发的重要方法.那么很明显,如果一个MotionEvent传 ...