Spring源码解析-环境变量(上)

“不积跬步,无以至千里”。

今天聊一聊Spring中环境变量的动态添加和填充Bean属性的时候一些带“$”符号的属性值的解析问题。

因为最近做项目的时候发现了一个有意思的问题,之前也没关注过。因为项目中使用的容器类型是GenericXmlApplicationContext,所以不会使用扫描的方式来读取bean,然后封装到BeanDefinitionMap中,而是采用读取xml配置文件的方式来加载bean,也就是使用bean标签的方式来配置bean,算是比较古老的方式,类似下面这种:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

  <bean id="people" class="com.example.spring.xmlbeans.People">
    <property name="name" value="${people.name}"/>
    <property name="age" value="${people.age}"/>
  </bean>
</beans>

可以发现,BeanA中有一个属性,且设置了set方法,然后赋值的时候是采用这种“$”的方式,让人很容易想到是从环境变量中读取一个people.name,然后在填充bean属性的时候从环境变量中拿出来就好了,其实不是这样的!!!因为刚开始我也是这么想的,然后当我清晰的看到spring的环境变量中确实有people.name这个key,但是在填充name属性的时候死活取不到值的时候,简直比阿根廷1:2爆冷输给沙特还更要懵逼!!!

先看我是怎么操作的:

public class MainTest {
    public static void main(String[] args) throws IOException {
        GenericXmlApplicationContext context = new GenericXmlApplicationContext();
        // 新建一个ResourcePropertySource,读取自定义的配置文件
        ResourcePropertySource resourcePropertySource = new ResourcePropertySource("beans-env.properties");
        // 调用容器的Api添加PropertySource,即添加自定义的配置到Spring的上下文环境中
        context.getEnvironment().getPropertySources().addLast(resourcePropertySource);
        context.load("beans.xml");
        context.refresh();
        context.registerShutdownHook();
        context.start();
    }
}
public class People implements ApplicationContextAware {
  private String name;
  private Integer age;

  public void setName(String name) {
    this.name = name;
  }

  public void setAge(Integer age) {
    this.age = age;
  }

  @Override
  public String toString() {
    return "People{" +
      "name='" + name + '\'' +
      ", age=" + age +
      '}';
  }

  @Override
  public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    System.out.println(applicationContext.getEnvironment().getProperty("People name: "+"people.name"));
    System.out.println(applicationContext.getEnvironment().getProperty("People age: "+"people.age"));
  }
}

beans-env.properties配置文件内容如下:

people.name=messi
people.age=34

请添加图片描述

通过断点,可以很清晰的看到当前环境变量中,确实已经添加了自定义的配置文件beans-env.properties,并且可以读取people.name这个配置项,然而当程序继续运行的时候,却发生了意料之外的BUG… …

请添加图片描述

由此可以推断出,对beanDefinitionMap中bean的属性进行填充的时候,“$”符号的解析并不是从spring的环境变量中读取的!!!

然而不久前,项目组内一个老哥给了个解决方案,在beans.xml文件中添加一个bean,问题解决了!

<bean id="propertyConifgurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
  <property name="location">
    <value>beans-env.properties</value>
  </property>
  <property name="fileEncoding">
    <value>utf-8</value>
  </property>
</bean>

请添加图片描述

所以现在有两个问题需要探索:

  1. 如何往Spring环境变量中添加自定义的环境变量?工作原理是什么?
  2. PropertyPlaceholderConfigurer这个类是怎么完成bean属性填充时“$”符号解析工作的?

让我们先把这两个问题梳理出来,后面的文章将会一一解答。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值