用过的springboot的小伙伴都知道springboot不须要再像springmvc引入那么多的配置文件,只须要加入application.properties或者application.yml便可,好比在上一篇文章讲到数据库的配置,只须要在文件引入以下的配置便可:java
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/zplxjj?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=@ZPLxjj12345
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
复制代码
下面简单介绍下springboot在启动的时候是在什么时候读取的properties和yml文件的内容的mysql
第一步:定义一个event,继承ApplicationEventspring
public class CustomerApplicationEvent extends ApplicationEvent {
public CustomerApplicationEvent(Object source) {
super(source);
System.out.println("CustomerApplicationEvent constructor...");
}
}
复制代码
第二步:定义一个listenersql
@Component
public class CustomerApplicationListener implements ApplicationListener<CustomerApplicationEvent> {
@Override
public void onApplicationEvent(CustomerApplicationEvent customerApplicationEvent) {
System.out.println("customerApplicationEvent:"+customerApplicationEvent.getClass().getName());
}
}
复制代码
第三步:注册监听器数据库
@SpringBootApplication
public class Application {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);
// 注册 CustomerApplicationListener 事件监听器
context.addApplicationListener(new CustomerApplicationListener());
// 发布 CustomerApplicationEvent 事件
context.publishEvent(new CustomerApplicationEvent(new Object()));
}
}
复制代码
启动项目后,会发现控制台输出了:springboot
CustomerApplicationEvent constructor...
customerApplicationEvent:com.stone.zplxjj.event.CustomerApplicationEvent
复制代码
加载配置文件须要用到ConfigFileApplicationListener,其代码以下:bash
@Override
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof ApplicationEnvironmentPreparedEvent) {
onApplicationEnvironmentPreparedEvent(
(ApplicationEnvironmentPreparedEvent) event);
}
if (event instanceof ApplicationPreparedEvent) {
onApplicationPreparedEvent(event);
}
}
复制代码
进入方法:onApplicationEnvironmentPreparedEvent微信
private void onApplicationEnvironmentPreparedEvent( ApplicationEnvironmentPreparedEvent event) {
List<EnvironmentPostProcessor> postProcessors = loadPostProcessors();
postProcessors.add(this);
AnnotationAwareOrderComparator.sort(postProcessors);
for (EnvironmentPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessEnvironment(event.getEnvironment(),
event.getSpringApplication());
}
}
复制代码
进入postProcessor.postProcessEnvironment:mvc
//类:ConfigFileApplicationListener
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
addPropertySources(environment, application.getResourceLoader());
}
复制代码
进入addPropertySourcesapp
protected void addPropertySources(ConfigurableEnvironment environment, ResourceLoader resourceLoader) {
//将随机方法放入到PropertySources中
RandomValuePropertySource.addToEnvironment(environment);
//load加载
new Loader(environment, resourceLoader).load();
}
复制代码
进入load方法:
public void load() {
this.profiles = new LinkedList<>();
this.processedProfiles = new LinkedList<>();
this.activatedProfiles = false;
this.loaded = new LinkedHashMap<>();
initializeProfiles();
while (!this.profiles.isEmpty()) {
Profile profile = this.profiles.poll();
if (profile != null && !profile.isDefaultProfile()) {
addProfileToEnvironment(profile.getName());
}
load(profile, this::getPositiveProfileFilter,
addToLoaded(MutablePropertySources::addLast, false));
this.processedProfiles.add(profile);
}
resetEnvironmentProfiles(this.processedProfiles);
load(null, this::getNegativeProfileFilter,
addToLoaded(MutablePropertySources::addFirst, true));
addLoadedPropertySources();
}
复制代码
进入字方法load
private void load(Profile profile, DocumentFilterFactory filterFactory, DocumentConsumer consumer) {
getSearchLocations().forEach((location) -> {
boolean isFolder = location.endsWith("/");
Set<String> names = isFolder ? getSearchNames() : NO_SEARCH_NAMES;
names.forEach(
(name) -> load(location, name, profile, filterFactory, consumer));
});
}
复制代码
/** * The "config location" property name. */
public static final String CONFIG_LOCATION_PROPERTY = "spring.config.location";
// Note the order is from least to most specific (last one wins)
private static final String DEFAULT_SEARCH_LOCATIONS = "classpath:/,classpath:/config/,file:./,file:./config/";
复制代码
**spring.config.name说明:**假如你不喜欢“application.properties”这个默认文件名,你能够从新设定:spring.config.name属性直接指定属性文件名称,spring.config.location属性指定明确路径,可是要注意不能写在application.properties文件里,这样会不起做用,能够写在java -jar xxx.jar --spring.config.name=custom.properties,还能够经过环境变量等方式,yml文件也能够这样
真正加载配置文件的方法:
private void load(String location, String name, Profile profile, DocumentFilterFactory filterFactory, DocumentConsumer consumer) {
if (!StringUtils.hasText(name)) {
for (PropertySourceLoader loader : this.propertySourceLoaders) {
if (canLoadFileExtension(loader, location)) {
load(loader, location, profile,
filterFactory.getDocumentFilter(profile), consumer);
return;
}
}
}
Set<String> processed = new HashSet<>();
for (PropertySourceLoader loader : this.propertySourceLoaders) {
for (String fileExtension : loader.getFileExtensions()) {
if (processed.add(fileExtension)) {
loadForFileExtension(loader, location + name, "." + fileExtension,
profile, filterFactory, consumer);
}
}
}
}
复制代码
loader.getFileExtensions():获取全部支持的文件后缀,loader初始化以下:
Loader(ConfigurableEnvironment environment, ResourceLoader resourceLoader) {
this.propertySourceLoaders = SpringFactoriesLoader.loadFactories(
PropertySourceLoader.class, getClass().getClassLoader());
}
复制代码
经过加载jar:spring-boot-2.1.4.RELEASE.jar:META-INF/spring.factories文件下对应内容:
# PropertySource Loaders
org.springframework.boot.env.PropertySourceLoader=\
org.springframework.boot.env.PropertiesPropertySourceLoader,\
org.springframework.boot.env.YamlPropertySourceLoader
复制代码
从这里咱们能够看到,经过PropertiesPropertySourceLoader和YamlPropertySourceLoader 加载配置文件,具体源码没有细看了,有兴趣自行阅读吧
加载完配置文件,调用方法:addLoadedPropertySources()
至此,springboot加载properties和yml的入口就分析到这里了,细节上确定不能面面俱到,可是入口知道了,后面就好分析了
本人也开通了微信公众号:stonezplxjj和我的博客:www.zplxjj.com,更多文章欢迎关注公众号: