Spring Environment(三)生命周期
Spring Environment(三)生命周期
Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html)
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(三)生命周期的更多相关文章
- Spring(三)--Spring bean的生命周期
Spring bean的生命周期 ApplicationContext Bean生命周期流程 1.需要的实体类 ackage com.xdf.bean; import org.springframew ...
- Spring Bean的生命周期(非常详细)
Spring作为当前Java最流行.最强大的轻量级框架,受到了程序员的热烈欢迎.准确的了解Spring Bean的生命周期是非常必要的.我们通常使用ApplicationContext作为Spring ...
- Spring Bean的生命周期详解(转)
Spring作为当前Java最流行.最强大的轻量级框架,受到了程序员的热烈欢迎.准确的了解Spring Bean的生命周期是非常必要的.我们通常使用ApplicationContext作为Spring ...
- Spring动态代理及Spring Bean的生命周期
数组添加值 public class DiTest { /** * 数组 */ private String [] arrays; /** * List:集合 */ private List<I ...
- 第37讲 谈谈Spring Bean的生命周期和作用域
在企业应用软件开发中,Java 是毫无争议的主流语言,开放的 Java EE 规范和强大的开源框架功不可没,其中 Spring 毫无疑问已经成为企业软件开发的事实标准之一.今天这一讲,我将补充 Spr ...
- Spring Bean的生命周期、Spring MVC的工作流程、IOC,AOP
1.Spring Bean的生命周期? (1)构造方法实例化bean. (2)构造方法设置对象属性. (3)是否实现aware接口,三种接口(BeanNameAware,BeanFactoryAwar ...
- 谈谈Spring bean的生命周期(一)
简介 本片文章主要讲Spring IOC容器中 bean 的生命周期 Spring bean 生命周期 Spring 中bean的声明周期 可以分为如下4个阶段: 实例化阶段--Instantiati ...
- Spring应用上下文生命周期
Spring应用上下文生命周期整体分成四个阶段 ConfigurableApplicationContext#refresh,加载或者刷新持久化配置 ConfigurableApplicationCo ...
- spring bean的生命周期
掌握好spring bean的生命周期,对spring的扩展大有帮助. spring bean的生命周期(推荐看) spring bean的生命周期
- Spring Bean的生命周期,《Spring 实战》书中的官方说法
连着两天的面试 ,都问到了 Spring 的Bean的生命周期,其中还包括 昨晚一波阿里的电话面试.这里找到了Spring 实战中的官方说法.希望各位要面试的小伙伴记住,以后有可能,或者是有时间 去看 ...
随机推荐
- Java多线程及线程状态转换
以下内容整理自:http://blog.csdn.net/wtyvhreal/article/details/44176369 线程:是指进程中的一个执行流程. 线程与进程的区别:每个进程都需要操作 ...
- Java中字节流和字符流复制文件
字节流和字符流复制文件的过程: 1.建立两个流对象 绑定数据源和目的地 2.遍历出需复制的文件写入复制过后的新文件中(只不过是遍历的时候是区分字节和字符的) 3.访问结束后关闭资源 字节流复制文件: ...
- yum update 自动忽略内核更新
系统每天凌晨 3 点自动执行 yum update 任务 但升级内核后,会出现下面情况 一些编译软件需要内核模块才能够被调用, 而内核模块需要与当前版本内核编译后才能够使用, 假设内核升级后,之前软件 ...
- 665. Non-decreasing Array
Given an array with n integers, your task is to check if it could become non-decreasing by modifying ...
- Ubuntu 16.04 LTS network DIASBLED解决办法
问题 昨天正浏览着网页,突然无法连接.但右上角的wifi信号显示仍然是连接状态.于是我尝试断开再重新连接一次,没想到刚断开就报了个内部错误,然后wifi图标直接消失了.重启后虽然有wifi图标,但无法 ...
- openvpn 使用账户密码认证
OpenVPN使用user/passwd完成验证登录 OpenVPN使用user/passwd完成验证登录1,为什么要使用user/passwd?比常规openvpn管理方便,删除用户只需要在pwd. ...
- Android使用VideoView播放本地视频及网络视频Demo
1.xm文件 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:and ...
- Python+Selenium学习--分页处理
场景 我们在测试一个web 应用时,经常出现翻页的情况,下面介绍翻页场景 代码 #!/usr/bin/env python # -*- codinfg:utf-8 -*- ''' @author: J ...
- oracle中获取当前整点和上一个小时整点,日期类型
select to_date(to_char(sysdate,'yyyy-mm-dd hh'),'yyyy-mm-dd hh:mi:ss') from dual;select to_date(to_c ...
- 定义一个servlet用于处理所有外部接口类 架构思路
架构思路”: 所有外部URL访问请求(对外提供的接口)全部交给intServiceServlet处理, 然后servlet调用BPO通过URL中的命名去寻找相应的javaBean.接口BO,然后接口B ...