Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master'
Browse files Browse the repository at this point in the history
# Conflicts:
#	spring-boot-tests/spring-boot-ymbj-tests/spring-boot-generaldemo-tests/src/main/resources/application.properties
  • Loading branch information
jinyue233 committed May 2, 2020
2 parents cf4e1a1 + d469368 commit 3fc67ad
Show file tree
Hide file tree
Showing 16 changed files with 103 additions and 117 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
6. [SpringBoot内置的各种Starter是怎样构建的? SpringBoot源码(六)](https://github.com/yuanmabiji/Java-SourceCode-Blogs/blob/master/SpringBoot/6%20SpringBoot%E5%86%85%E7%BD%AE%E7%9A%84%E5%90%84%E7%A7%8DStarter%E6%98%AF%E6%80%8E%E6%A0%B7%E6%9E%84%E5%BB%BA%E7%9A%84%EF%BC%9F%20%20SpringBoot%E6%BA%90%E7%A0%81%EF%BC%88%E5%85%AD%EF%BC%89.md)
7. [SpringBoot的启动流程是怎样的?SpringBoot源码(七)](https://github.com/yuanmabiji/Java-SourceCode-Blogs/blob/master/SpringBoot/7%20SpringBoot%E7%9A%84%E5%90%AF%E5%8A%A8%E6%B5%81%E7%A8%8B%E6%98%AF%E6%80%8E%E6%A0%B7%E7%9A%84%EF%BC%9FSpringBoot%E6%BA%90%E7%A0%81%EF%BC%88%E4%B8%83%EF%BC%89.md)
8. [SpringApplication对象是如何构建的? SpringBoot源码(八)](https://github.com/yuanmabiji/Java-SourceCode-Blogs/blob/master/SpringBoot/8%20SpringApplication%E5%AF%B9%E8%B1%A1%E6%98%AF%E5%A6%82%E4%BD%95%E6%9E%84%E5%BB%BA%E7%9A%84%EF%BC%9F%20SpringBoot%E6%BA%90%E7%A0%81%EF%BC%88%E5%85%AB%EF%BC%89.md)
9. 持续更新中...
9. **持续更新中...**


* 更多源码分析文章请跳转至:https://github.com/yuanmabiji/Java-SourceCode-Blogs
Expand Down
57 changes: 0 additions & 57 deletions README.md___jb_tmp___

This file was deleted.

2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@
<module>spring-boot-project</module>
<!-- Samples are built via the invoker plugin -->
<!--新增spring-boot-samples模块-->
<module>spring-boot-samples</module>
<!--<module>spring-boot-samples</module>-->
<module>spring-boot-samples-invoker</module>
<module>spring-boot-tests</module>
</modules>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoCo

# Auto Configuration Import Filters
org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\
org.springframework.boot.autoconfigure.condition.OnBeanCondition,\
org.springframework.boot.autoconfiSpringApplicationRunListenergure.condition.OnBeanCondition,\
org.springframework.boot.autoconfigure.condition.OnClassCondition,\
org.springframework.boot.autoconfigure.condition.OnWebApplicationCondition

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -364,13 +364,7 @@ public ConfigurableApplicationContext run(String... args) {
// 7)》》》》》发射【ApplicationPreparedEvent】事件,标志Context容器已经准备完成
prepareContext(context, environment, listeners, applicationArguments,
printedBanner);
// 这个语句是我自己加上去的,spring容器刷新完毕后用来打印容器中加载的bean信息
String[] definitionNames = context.getBeanDefinitionNames();
System.out.println("=======================1111=============================");
for (String name : definitionNames) {
System.out.println(name);
}
System.out.println("=======================1111=============================");

// 【7】刷新容器,这一步至关重要,以后会在分析Spring源码时详细分析,主要做了以下工作:
// 1)在context刷新前做一些准备工作,比如初始化一些属性设置,属性合法性校验和保存容器中的一些早期事件等;
// 2)让子类刷新其内部bean factory,注意SpringBoot和Spring启动的情况执行逻辑不一样
Expand All @@ -387,13 +381,7 @@ public ConfigurableApplicationContext run(String... args) {
// 11)完成容器bean factory的初始化,并初始化所有剩余的单例bean。这一步非常重要,一些bean postprocessor会在这里调用。
// 12)完成容器的刷新工作,并且调用生命周期处理器的onRefresh()方法,并且发布ContextRefreshedEvent事件
refreshContext(context);
// 这个语句是我自己加上去的,spring容器刷新完毕后用来打印容器中加载的bean信息
/* String[] definitionNames = context.getBeanDefinitionNames();*/
System.out.println("=======================2222=============================");
for (String name : definitionNames) {
System.out.println(name);
}
System.out.println("=======================2222=============================");

// 【8】执行刷新容器后的后置处理逻辑,注意这里为空方法
afterRefresh(context, applicationArguments);
// 停止stopWatch计时
Expand All @@ -403,25 +391,11 @@ public ConfigurableApplicationContext run(String... args) {
new StartupInfoLogger(this.mainApplicationClass)
.logStarted(getApplicationLog(), stopWatch);
}
System.out.println("=======================3333=============================");
for (String name : definitionNames) {
System.out.println(name);
}
System.out.println("=======================3333=============================");

// 》》》》》发射【ApplicationStartedEvent】事件,标志spring容器已经刷新,此时所有的bean实例都已经加载完毕
listeners.started(context);
System.out.println("=======================4444=============================");
for (String name : definitionNames) {
System.out.println(name);
}
System.out.println("=======================4444=============================");
// 【9】调用ApplicationRunner和CommandLineRunner的run方法,实现spring容器启动后需要做的一些东西比如加载一些业务数据等
callRunners(context, applicationArguments);
System.out.println("=======================5555=============================");
for (String name : definitionNames) {
System.out.println(name);
}
System.out.println("=======================5555=============================");

}
// 【10】若启动过程中抛出异常,此时用FailureAnalyzers来报告异常
Expand All @@ -440,17 +414,22 @@ public ConfigurableApplicationContext run(String... args) {
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}


// 这个语句是我自己加上去的,spring容器刷新完毕后用来打印容器中加载的bean信息
String[] definitionNames = context.getBeanDefinitionNames();
/** TODO
* **思考**: SpringBoot的`run`方法会调用`prepareContext`会加载一些`bean`,
* 同时,在调用`AbstractApplicationContext`的`refresh`方法时也会加载一些`bean`,这些加载的`bean`有什么不同?
*/
// TODO 只有在这一步才会打印剩下的bean,不是在prepareEnvironment加载的bean???
System.out.println("=======================6666=============================");
System.out.println("=======================下面开始打印容器中所有的bean name=============================");
for (String name : definitionNames) {
System.out.println(name);
}
System.out.println("=======================6666=============================");
System.out.println("=======================打印容器中所有的bean name结束=============================");


// 【11】最终返回容器
return context;
}
Expand Down Expand Up @@ -533,7 +512,10 @@ private void configureHeadlessProperty() {
}

private SpringApplicationRunListeners getRunListeners(String[] args) {
// 构造一个由SpringApplication.class和String[].class组成的types
Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
// 1) 根据SpringApplicationRunListener接口去spring.factories配置文件中加载其SPI扩展实现类
// 2) 构建一个SpringApplicationRunListeners对象并返回
return new SpringApplicationRunListeners(logger, getSpringFactoriesInstances(
SpringApplicationRunListener.class, types, this, args));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,10 @@ class SpringApplicationRunListeners {
}

public void starting() {
// 遍历listeners集合,这里实质取出的就是刚才从spring.factories中取出的SPI实现类EventPublishingRunListener
// 而EventPublishingRunListener对象承担了SpringBoot启动过程中负责广播不同的生命周期事件
for (SpringApplicationRunListener listener : this.listeners) {
// 调用EventPublishingRunListener的starting方法来广播ApplicationStartingEvent事件
listener.starting();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,13 @@ public class AnsiOutputApplicationListener
@Override
public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
ConfigurableEnvironment environment = event.getEnvironment();
// 由于存在spring.output.ansi.enabled的系统属性,因此可以通过这条语句可以禁止彩色输出
// environment.getSystemProperties().put("spring.output.ansi.enabled", "never");
Binder.get(environment)
.bind("spring.output.ansi.enabled", AnsiOutput.Enabled.class)
.ifBound(AnsiOutput::setEnabled);
System.out.println("AnsiOutputApplicationListener: spring.output.ansi.enabled=" + environment.getProperty("spring.output.ansi.enabled"));
System.out.println("AnsiOutputApplicationListener: spring.output.ansi.console-available=" + environment.getProperty("spring.output.ansi.console-available"));
AnsiOutput.setConsoleAvailable(environment
.getProperty("spring.output.ansi.console-available", Boolean.class));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,17 +53,21 @@ public class DelegatingApplicationListener

@Override
public void onApplicationEvent(ApplicationEvent event) {
// 这里监听ApplicationEnvironmentPreparedEvent事件,说明环境变量已经准备好,
// 然后再把配置文件配置的context.listener.classes监听器加载出来放到multicaster对象的Listerner集合中
if (event instanceof ApplicationEnvironmentPreparedEvent) {
List<ApplicationListener<ApplicationEvent>> delegates = getListeners(
((ApplicationEnvironmentPreparedEvent) event).getEnvironment());
if (delegates.isEmpty()) {
return;
}
// 这里新建一个SimpleApplicationEventMulticaster对象来派发事件
this.multicaster = new SimpleApplicationEventMulticaster();
for (ApplicationListener<ApplicationEvent> listener : delegates) {
this.multicaster.addApplicationListener(listener);
}
}
// 这里直接委托配置文件配置的监听器来监听该事件即将事件委托给通过context.listener.classes配置的自定义的监听器处理。
if (this.multicaster != null) {
this.multicaster.multicastEvent(event);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,19 @@ public class EventPublishingRunListener implements SpringApplicationRunListener,
private final SpringApplication application;

private final String[] args;

/**
* 拥有一个SimpleApplicationEventMulticaster事件广播器来广播事件
*/
private final SimpleApplicationEventMulticaster initialMulticaster;

public EventPublishingRunListener(SpringApplication application, String[] args) {
this.application = application;
this.args = args;
// 新建一个事件广播器SimpleApplicationEventMulticaster对象
this.initialMulticaster = new SimpleApplicationEventMulticaster();
// 遍历在构造SpringApplication对象时从spring.factories配置文件中获取的事件监听器
for (ApplicationListener<?> listener : application.getListeners()) {
// 将从spring.factories配置文件中获取的事件监听器们添加到相关集合中缓存起来
this.initialMulticaster.addApplicationListener(listener);
}
}
Expand All @@ -63,25 +68,27 @@ public EventPublishingRunListener(SpringApplication application, String[] args)
public int getOrder() {
return 0;
}

// 》》》》》发射【ApplicationStartingEvent】事件
@Override
public void starting() {
// EventPublishingRunListener对象将发布ApplicationStartingEvent这件事情委托给了initialMulticaster对象
// 调用initialMulticaster的multicastEvent方法来发射ApplicationStartingEvent事件
this.initialMulticaster.multicastEvent(
new ApplicationStartingEvent(this.application, this.args));
}

// 》》》》》发射【ApplicationEnvironmentPreparedEvent】事件
@Override
public void environmentPrepared(ConfigurableEnvironment environment) {
this.initialMulticaster.multicastEvent(new ApplicationEnvironmentPreparedEvent(
this.application, this.args, environment));
}

// 》》》》》发射【ApplicationContextInitializedEvent】事件
@Override
public void contextPrepared(ConfigurableApplicationContext context) {
this.initialMulticaster.multicastEvent(new ApplicationContextInitializedEvent(
this.application, this.args, context));
}

// 》》》》》发射【ApplicationPreparedEvent】事件
@Override
public void contextLoaded(ConfigurableApplicationContext context) {
for (ApplicationListener<?> listener : this.application.getListeners()) {
Expand All @@ -93,19 +100,19 @@ public void contextLoaded(ConfigurableApplicationContext context) {
this.initialMulticaster.multicastEvent(
new ApplicationPreparedEvent(this.application, this.args, context));
}

// 》》》》》发射【ApplicationStartedEvent】事件
@Override
public void started(ConfigurableApplicationContext context) {
context.publishEvent(
new ApplicationStartedEvent(this.application, this.args, context));
}

// 》》》》》发射【ApplicationReadyEvent】事件
@Override
public void running(ConfigurableApplicationContext context) {
context.publishEvent(
new ApplicationReadyEvent(this.application, this.args, context));
}

// 》》》》》发射【ApplicationFailedEvent】事件
@Override
public void failed(ConfigurableApplicationContext context, Throwable exception) {
ApplicationFailedEvent event = new ApplicationFailedEvent(this.application,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,10 @@ public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof ApplicationStartingEvent) {
onApplicationStartingEvent((ApplicationStartingEvent) event);
}
// 注意加载application.properties配置文件属性也是由ApplicationEnvironmentPreparedEvent事件触发ConfigFileApplicationListener监听器来加载的
// 而LoggingApplicationListener也是监听ApplicationEnvironmentPreparedEvent这个事件,而此时application.properties配置文件配置已经加载完毕
// 因此这里注意不同监听器同样是监听onApplicationEnvironmentPreparedEvent事件,而不同监听器却有执行顺序的,这是由spring.factories配置文件配置加载后,
// 还要执行AnnotationAwareOrderComparator.sort(instances);语句进行排序,TODO 【思考】监听器的排序规则是在哪里设置的呢???
else if (event instanceof ApplicationEnvironmentPreparedEvent) {
onApplicationEnvironmentPreparedEvent(
(ApplicationEnvironmentPreparedEvent) event);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,9 @@
package com.ymbj.autoconfig;
package com.ymbj;

import com.ymbj.hellowolrd.autoconfig.HelloWorldEnableAutoConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.AutoConfigurationPackage;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.core.env.PropertyResolver;

import java.util.Properties;

@SpringBootApplication
public class MainApplication {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
package com.ymbj.autoconfig;
package com.ymbj.customlistener;

import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
import org.springframework.boot.context.event.ApplicationStartingEvent;
import org.springframework.context.ApplicationListener;

public class CustomListener implements ApplicationListener<ApplicationEnvironmentPreparedEvent> {
/**
* /自定义一个监听器监听SpringBoot的生命周期事件(注意不是Spring的内置生命周期事件哈)
* 注意若是SpringBoot自定义事件监听器则需要通过SpringBoot的SPI机制来加载到相应集合,而不是通过@Component来加载。
*/
public class CustomSpringBootListener implements ApplicationListener<ApplicationEnvironmentPreparedEvent> {

/**
* Handle an application event.
Expand Down
Loading

0 comments on commit 3fc67ad

Please sign in to comment.