ClassPathXmlApplicationContext

      在我的 BeanFactory 容器文章中主要提及了 BeanFactory 容器初始化(Spring 配置文件加载(还没解析))的一些过程结合源码进行分析。那么,本篇文章主要对

  ClassPathXmlApplicationContext cp = new ClassPathXmlApplicationContext("bean3.xml");

  Spring 配置文件路径占位符加载、解析的过程结合源码进行分析,本篇也不会对 配置文件的解析过程进行分析,解析过程我会在后面再进行说明,因为涉及到的东西实在太多了!

  使用 BeanFactory 和 ClassPathXmlApplicationContext 在加载配置文件时是有相同操作的。

ClassPathXmlApplicationContext关系图

Spring 文档

aaarticlea/png;base64,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" alt="" />

                            (Spring 文档关系图)

UML

  

                           (UML 图)

构造方法

      实例化 ClassPathXmlApplicationContext 传入一个字符串(配置文件名称),所以调用下面构造方法

  

                              ((String configLocation) 构造方法)

    之后调用本类的另一个构造方法

public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException {
     //一直调用父类构造,直到 AbstractApplicationContext,设置一个空的 ApplicationContext 对象
super(parent);
     //设置配置文件路径
setConfigLocations(configLocations);
     //默认为 true
if (refresh) {
refresh();
}
}

    父类 AbstractApplicationContext 构造方法

public AbstractApplicationContext(ApplicationContext parent) {
  //调用本类的无参构造
this();
setParent(parent);
}

    AbstractApplicationContext 无参构造方法

public AbstractApplicationContext() {
this.resourcePatternResolver = getResourcePatternResolver();
}

    AbstractApplicationContext.getResourcePatternResolver()

protected ResourcePatternResolver getResourcePatternResolver() {
return new PathMatchingResourcePatternResolver(this);
}

    从 PathMatchingResourcePatternResolver 类上的注释可知 该类支持 Ant 风格的路径解析。

设置配置文件路径

      在 ClassPathXmlApplicationContext 构造方法中调用了 setConfigLocations(配置文件路径数组)

    setConfigLocations(configLocations)

public void setConfigLocations(String... locations) {
if (locations != null) {
Assert.noNullElements(locations, "Config locations must not be null");
       //configLocations 是一个 String 类型的数组
this.configLocations = new String[locations.length];
       //遍历路径数组,将 解析(分解) 后的路径放到 configLocations 中
for (int i = 0; i < locations.length; i++) {
          //resolvePath() 方法用于解析路径
this.configLocations[i] = resolvePath(locations[i]).trim();
}
}
else {
this.configLocations = null;
}
}

    resolvePath()方法

protected String resolvePath(String path) {
return getEnvironment().resolveRequiredPlaceholders(path);
}

    getEnvironment() 是 ConfigurableApplicationContext 接口的方法,AbstractApplicationContext 对其进行了重写

    

                 (getEnvironment() 方法)

    很简单,当前 ConfigurableEnvironment 对象为空就创建一个,不为空就直接返回。

  注意

    上面说到了创建一个 ConfigurableEnvironment 对象返回,但是其中还发生了一些其他事情,如下

      首先是 createEnvironment() 方法,很简单,就创建一个 StandardEnvironment 对象

protected ConfigurableEnvironment createEnvironment() {
return new StandardEnvironment();
}

      但是,StandardEnvironment 类继承自 AbstractEnvironment 类,StandardEnvironment 类只有一个无参的构造方法,所以,在初始化 StandardEnvironment 时,便会调用父类 AbstractEnvironment 类的无参构造方法,如下

public AbstractEnvironment() {
  //调用方法
customizePropertySources(this.propertySources);
//一个日志输出
}

      StandardEnvironment 类对 customizePropertySources() 方法进行了重写,下面就是来到重写后的 customizePropertySources() 方法

@Override
protected void customizePropertySources(MutablePropertySources propertySources) {
  /*
   SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME: systemProperties
   SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME: systemEnvironment
  */
propertySources.addLast(new MapPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties()));
propertySources.addLast(new SystemEnvironmentPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment()));
}

      AbstractEnvironment.getSystemProperties(),如下

public Map<String, Object> getSystemProperties() {
try {
     //首先获取全部属性
return (Map) System.getProperties();
}
catch (AccessControlException ex) {
return (Map) new ReadOnlySystemAttributesMap() {
@Override
protected String getSystemAttribute(String attributeName) {
try {
            //如果获取全部属性失败,则获取单个指定属性
            //如果获取单个还是不行则抛出异常
return System.getProperty(attributeName);
}
catch (AccessControlException ex) {
if (logger.isInfoEnabled()) {
logger.info(format("Caught AccessControlException when accessing system " +
"property [%s]; its value will be returned [null]. Reason: %s",
attributeName, ex.getMessage()));
}
return null;
}
}
};
}
}

      getSystemEnvironment()方法的逻辑和 getSystemProperties() 方法的实现差不多的。只是最后使用 System.getenv() 来获取。

   Environment

    Environment是一个接口,代表了当前应用程序所处的环境,从下面 UML 图中的大部分方法中可以看出 该接口主要和 profile、property有关。

    

          (http://www.cnblogs.com/dream-saddle/gallery/image/215409.html)

    profile

      profile 是 Spring3.1开始有的。详情见下面几篇文章吧

      https://www.cnblogs.com/strugglion/p/7091021.html

      另外我们可以使用下面这种方式进行设置当前使用的 profile

     aaarticlea/png;base64,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" alt="" />

                          (设置 profile)

    property

      property 就是应用程序运行时的参数

  配置文件路径中 placeholder(占位符)解析

    为什么需要解析 placeholder?因为我们可以这样写:

//自定义一个系统属性,名为 spring 值为 *1(PathMatchingResourcePatternResolver 支持 Ant 风格的路径解析) 或配置文件全名
System.setProperty("spring", "*1");
//使用占位符设置配置文件路径
ClassPathXmlApplicationContext cp = new ClassPathXmlApplicationContext("${spring}.xml"); //通过下面步骤的解析,最后得到的路径就是 *1.xml

    resolveRequiredPlaceholders(path)

      该方法是 PropertyResovler 接口定义(该接口关系图在上面已经有了)的方法,所以,来到其实现类 AbstractEnvironment 进行了重写。

@Override
public String resolveRequiredPlaceholders(String text) throws IllegalArgumentException {
  //propertyResolver private final ConfigurablePropertyResolver propertyResolver = new PropertySourcesPropertyResolver(this.propertySources);
  //text 就是传过来的配置文件路径 如 classpath:bean.xml
return this.propertyResolver.resolveRequiredPlaceholders(text);
}

      继续跟踪来到 AbstractPropertyResolver.resolveRequiredPlaceholders(String text)

@Override
public String resolveRequiredPlaceholders(String text) throws IllegalArgumentException {
  //strictHelper 是 PropertyPlaceholderHelper 对象,如果为空就创建一个
if (this.strictHelper == null) {
this.strictHelper = createPlaceholderHelper(false);
}
  //开始解析占位符
return doResolvePlaceholders(text, this.strictHelper);
}

      AbstractPropertyResolver.createPlaceholderHelper(boolean ignoreUnresolvablePlaceholders)

private PropertyPlaceholderHelper createPlaceholderHelper(boolean ignoreUnresolvablePlaceholders) {
  /*
  placeholderPrefix: ${
  placholderSuffix: }
  valuleSeparator: :
  ignoreUnresolvablePlaceholders: 默认 false
  */
return new PropertyPlaceholderHelper(this.placeholderPrefix, this.placeholderSuffix,
this.valueSeparator, ignoreUnresolvablePlaceholders);
}

      AbstractPropertyResolver.doResolverPlaceholders(String text, PropertyPlaceholderHelper helper)

private String doResolvePlaceholders(String text, PropertyPlaceholderHelper helper) {
  //继续调用
return helper.replacePlaceholders(text, new PropertyPlaceholderHelper.PlaceholderResolver() {
@Override
public String resolvePlaceholder(String placeholderName) {
return getPropertyAsRawString(placeholderName);
}
});
}

      PropertyPlaceholderHelper.replacePlaceholders(String value, PlaceholderResolver placeholderResolver)

/**
* Replaces all placeholders of format {@code ${name}} with the value returned
* from the supplied {@link PlaceholderResolver}.
   * 替换所有的占位符*/
public String replacePlaceholders(String value, PlaceholderResolver placeholderResolver) {
Assert.notNull(value, "'value' must not be null");
return parseStringValue(value, placeholderResolver, new HashSet<String>());
}

      继续调用本类的 parseStringValue() 方法,这个方法代码挺多的,这里只说明几个重要的部分吧,请读者结合源码阅读!

/*
this.placeholderPrefix: ${
this.placeholderSuffix: }
this.valueSeparator: :
*/
protected String parseStringValue(
String strVal, PlaceholderResolver placeholderResolver, Set<String> visitedPlaceholders) { StringBuilder result = new StringBuilder(strVal);

  //获取 ${ 在路径中的位置,用于判断是否需要进行解析,如果没有就直接返回
int startIndex = strVal.indexOf(this.placeholderPrefix);
while (startIndex != -1) {
     //获取占位符字符串的最后一个字符串索引 如:${config}.xml,就是 ${config} 的长度
     //获取长度只是个客观说法,但是实际逻辑并不是这样,而是获取 "}" 的位置,具体还请读者跟进方法查看
int endIndex = findPlaceholderEndIndex(result, startIndex);
if (endIndex != -1) {
       //获取占位符 即${} 中的部分
String placeholder = result.substring(startIndex + this.placeholderPrefix.length(), endIndex);
String originalPlaceholder = placeholder;
if (!visitedPlaceholders.add(originalPlaceholder)) {
throw new ...;
}
// Recursive invocation, parsing placeholders contained in the placeholder key.
       //递归调用了一次
placeholder = parseStringValue(placeholder, placeholderResolver, visitedPlaceholders);
// Now obtain the value for the fully resolved key...
       //根据占位符从 systemProperties,systemEnvironment 中获取值,获取的就是 System.setProperty(key, value) 中的 value
String propVal = placeholderResolver.resolvePlaceholder(placeholder);
if (propVal == null && this.valueSeparator != null) {
int separatorIndex = placeholder.indexOf(this.valueSeparator);
if (separatorIndex != -1) {
String actualPlaceholder = placeholder.substring(0, separatorIndex);
String defaultValue = placeholder.substring(separatorIndex + this.valueSeparator.length());
propVal = placeholderResolver.resolvePlaceholder(actualPlaceholder);
if (propVal == null) {
propVal = defaultValue;
}
}
}
if (propVal != null) {
// Recursive invocation, parsing placeholders contained in the
// previously resolved placeholder value.
propVal = parseStringValue(propVal, placeholderResolver, visitedPlaceholders);
         //将获取到的值进行替换,得到的就是配置文件真实名称
result.replace(startIndex, endIndex + this.placeholderSuffix.length(), propVal);
if (logger.isTraceEnabled()) {
...;
}
startIndex = result.indexOf(this.placeholderPrefix, startIndex + propVal.length());
}
else if (this.ignoreUnresolvablePlaceholders) {
// Proceed with unprocessed value.
startIndex = result.indexOf(this.placeholderPrefix, endIndex + this.placeholderSuffix.length());
}
else {
throw new ...;
}
visitedPlaceholders.remove(originalPlaceholder);
}
else {
startIndex = -1;
}
} return result.toString();
}

      到这里,整个配置文件路径的解析,设置就结束了。

      System.setProperty("spring", "*1");
           ApplicationContext cp = new ClassPathXmlApplicationContext("${spring}.xml");

      就是将 ${spring}.xml 中的 spring 解析出来,然后替换为 *1,最后存入到 AbstractRefreshableConfigApplicationContext 类的 configLocations 数组中。

      接着就是读取配置文件、解析、注册Bean,太多了,还是等到后面再说吧!

      我们已经知道 setConfigLocations(configLocations) 方法可以将 ${xxx}.xml 这样的 xml 配置解析为 xxx.xml 了,但是这个 xxx 可以是我们随意指定的 一个 Ant 风格的路径,那又是怎么解析的呢? 接着就是 refresh() 方法,后面会介绍到!

最新文章

  1. 透析Express.js
  2. ACM 矩阵题目整理
  3. LPC43xx SGPIO Pattern Match Mode
  4. react-native Unrecognized font family ‘Lonicons’;
  5. 将double类型的值保留几位小数
  6. C#命令模式-设计模式学习
  7. 可能是最好的SQL入门教程
  8. Wolsey“强整数规划模型”经典案例之一单源固定费用网络流问题
  9. textarea高度自适应(转载)
  10. Light OJ 1011
  11. ionic2一个需求模块的文件该是这样子的
  12. Oracle 学习笔记(六)
  13. C++ Primer读书笔记(1)
  14. 使用arguments对象验证函数的参数是否合法
  15. 教你如何自学UI设计
  16. JavaWeb总结(十三)
  17. 利用Python进行端口扫描
  18. canvas小球 时间倒计时demo-优化
  19. SQL夯实基础(九)MySQL联接查询算法
  20. dev GridControl显示标题

热门文章

  1. [C陷阱和缺陷] 第7章 可移植性缺陷
  2. 状态压缩+枚举 POJ 3279 Fliptile
  3. Android 性能优化(7)网络优化( 3) Optimizing User-Initiated Network Use
  4. java list遍历三种方法
  5. UIPickerView 多级联动
  6. Python之绘图和可视化
  7. Farseer.net轻量级开源框架 入门篇:修改数据详解
  8. GPC:使用GPC计算intersection容易出现的问题
  9. Jmeter之计数器
  10. 大数低速幂运算模板(c++)+python大数幂