我们如果要从springboot的环境中获取到配置文件的属性,只要注入一个Environment,然后直接调用getProperty(),方法就可以获取到。
@Autowired
Environment environment;
....
environment.getProperty("pro");
那么environment是怎么读取到我们定义的配置文件(例如application.properties、application-active.properties、application.yml、application-active.yml、nacos配置等)中的属性的呢?他们的顺序又是怎么样的呢?
接下来进入解密时刻,见证奇迹,额。有点长。
当我们调用environment.getProperty(“pro”)时候,具体执行的方法是PropertySourcesPropertyResolver 中的getProperty,不要问我为啥是它,反正就是!
public class PropertySourcesPropertyResolver extends AbstractPropertyResolver {
...
@Nullable
protected <T> T getProperty(String key, Class<T> targetValueType, boolean resolveNestedPlaceholders) {
if (this.propertySources != null) {
//会循环propertySources
for (PropertySource<?> propertySource : this.propertySources) {
if (logger.isTraceEnabled()) {
logger.trace("Searching for key '" + key + "' in PropertySource '" +
propertySource.getName() + "'");
}
Object value = propertySource.getProperty(key);
if (value != null) {
if (resolveNestedPlaceholders && value instanceof String) {
value = resolveNestedPlaceholders((String) value);
}
logKeyFound(key, propertySource, value);
return convertValueIfNecessary(value, targetValueType);
}
}
}
if (logger.isTraceEnabled()) {
logger.trace("Could not find key '" + key + "' in any property source");
}
return null;
}
...
}
所以我们只要搞清楚 属性propertySources是怎么赋值的,就可以知道读取配置文件的秘密了!
刚才说environment.getProperty(“pro”)时候,具体执行的方法是PropertySourcesPropertyResolver 中的getProperty,刷了流氓,还是要看下为啥是执行这个方法,我是怎么知道的呢?对就是它,debug出来的
@Component
public class PropertyCommand implements CommandLineRunner {
@Autowired
Environment environment;
@Override
public void run(String... args) throws Exception {
//来 搞个断点
System.out.println(environment.getProperty("pro"));
}
}
执行的是AbstractEnvironment中的getProperty(),那他是怎么跑到PropertySourcesPropertyResolver 中的呢?
public abstract class AbstractEnvironment implements ConfigurableEnvironment {
//还是只看我们关注的
private final MutablePropertySources propertySources = new MutablePropertySources();
private final ConfigurablePropertyResolver propertyResolver =
new PropertySourcesPropertyResolver(this.propertySources);
...
@Override
@Nullable
public String getProperty(String key) {
return this.propertyResolver.getProperty(key);
}
...
}
来到我们的要讲的重点对象了AbstractEnvironment ,想要知道这个对象是啥时候作用的,还是要看springboot的启动流程,哇重点了,跟写作文一样的点睛!
SpringApplication.run(xxx.class, args);,必须加粗,我们在main方法中都会执行这个方法,然后它就起来了,进入看下流程,重点关注SpringApplication 类
public class SpringApplication {
//还是只贴我们关注的
//1: 执行这个方法
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
return run(new Class<?>[] {
primarySource }, args);
}
//2: 执行这个方法
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
//要去构造一个SpringApplication,再run起来
return new SpringApplication(primarySources).run(args);
}
//3: 执行它,注意这个参数是我们传进来的xxx.class,后面有大作用
public SpringApplication(Class<?>... primarySources) {
this(null, primarySources);
}
//4: 看看都构造了哪些东西
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.