SpringBoot⼊门教程04——Environment详解
SpringBoot⼊门教程04——Environment详解
前⾔
上⼀节我们讲述了SpringBoot配置⽂件详解
细⼼的同学会发现⾥⾯其实有⼀个⼩坑
⽐如我们修改user.properties⽂件,修改后内容如下:
user.name=henry1111
user.age=16
Henry-16
跟预期的henry1111-16不太⼀样,为什么呢?
我们再看⼀个例⼦
引⼊Environment
在controller包下,新建EnvController类,内容如下
@RestController
public class EnvController {
@Autowired
private Environment env;
@RequestMapping("/env")
public String env(){
System.out.Property("user.name"));
System.out.Property("user.age"));
Property("user.name")+"-"+Property("user.age");
}
}
Henry-16
StandardServletEnvironment
如图,env实质是StandardServletEnvironment类的实例,继续追踪代码可知,getProperty实质就是遍历循环propertySources,如果当前Property(key)的值为null就继续遍历,如果值不为null就直接返回该值
PropertySourcesPropertyResolver类getProperty⽅法代码如下
@Nullable
protected<T> T getProperty(String key, Class<T> targetValueType,boolean resolveNestedPlaceholders){
if(this.propertySources != null){
Iterator var4 =this.propertySources.iterator();
while(var4.hasNext()){
PropertySource<?> propertySource =(();
if(this.logger.isTraceEnabled()){
ace("Searching for key '"+ key +"' in PropertySource '"+ Name()+"'");
}
Object value = Property(key);
if(value != null){
if(resolveNestedPlaceholders && value instanceof String){
value =solveNestedPlaceholders((String)value);
}
this.logKeyFound(key, propertySource, value);
vertValueIfNecessary(value, targetValueType);
}
}
}
if(this.logger.isTraceEnabled()){
ace("Could not find key '"+ key +"' in any property source");
}
return null;
}
在本例中env的propertySources有11个元素,其中最后⼀个元素对应到我们⾃定义的配置⽂件user.properties,
可以看到该元素中user.name和user.age与配置⽂件中是⼀致的,但是该元素是在列表最末,假如前⾯的元素中已经能到user.name,那么Property(“user.name”)返回的就是别的值。
那就试着去⼀下user.name,在第5个元素,下标为4的systemProperties中果然到了user.name。
鉴于⼀个⼀个⽐较⿇烦,我们⽤代码打印⼀下environment中都有哪些key值,修改⼀下EnvController,代码如下:
@RestController
public class EnvController {
@Autowired
private Environment env;
@RequestMapping("/env")
public String env(){springboot中文
StandardServletEnvironment environment =(StandardServletEnvironment) env;
MutablePropertySources propertySources = PropertySources();
Iterator<PropertySource<?>> iterator = propertySources.iterator();
while(iterator.hasNext()){
PropertySource<?> propertySource = ();
if(propertySource instanceof MapPropertySource){
MapPropertySource mapPropertySource =(MapPropertySource) propertySource;
String[] propertyNames = PropertyNames();
for(String s : propertyNames){
System.out.println(s+":"+Property(s));
}
}
}
Property("user.name")+"-"+Property("user.age");
}
}
执⾏⽇志,我就不贴了,⼤家可以⾃⼰跑⼀下看看输出。
总结
学完本节,我们对Springboot配置⽂件的加载过程应该有⽐较深的理解,下⾯做⼀个简单总结
JVM启动时,系统属性和环境变量传递给JVM
springboot启动时先扫描@Controller,@Component,@Configuration,@Service等注解,到声明让spring容器管理实例的类
看这些类上有没有@PropertySource注解,如果有则去加载该注解指定的配置⽂件
把所有的配置信息都给到Environment实例管理,配置信息根据来源不同有不同的优先级,⽐如系统属性和环境变量的优先级⾼于⽤户⾃定义properties⽂件的优先级
再判断这些类上有没有@ConfigurationProperties注解,如果有则从Environment实例中取值通过反射赋值
@Value注解与@ConfigurationProperties注解类似,也从Environment实例中取值通过反射赋值
踩坑
@PropertySource("") 时,idea开发环境启动也都成功,但是通过maven打包运⾏,就会报java.lang.IllegalArgumentException: Malformed \uxxxx encoding.
关于这个错误,⽹上⼤部分说配置⽂件中有’\‘或者⽂件路径有中⽂,检查了半天也没到’\'和中⽂,⼀开始百思不得其解,后⾯才仔细研究了⼀下springboot配置⽂件启动加载的过程,才有了本篇⽂章
看完⽂本我们知道,
@PropertySource注解只要在⼀个被spring容器管理的类上,那么不管在哪个类上实质是⼀样的,只是我们⼀般会写在对应的JavaBean配置类上
@PropertySource("")没有指定⽂件名,该注解等于没⽤
去掉@PropertySource("") 注解maven打包运⾏⽴马正常了
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论