自动装配原理.
POM.xml.
核心依赖 在父工程中(含有大量的依赖)
- 核心依赖:
spring-boot-dependencies- 其子依赖:
spring-boot-starter-parent- 项目依赖:
springbootstudy
- 项目依赖:
- 其子依赖:

启动器.
Spring Boot的启动场景
- 需要什么功能,就使用相应的启动器
- 如spring-boot-starter-web 会帮我们自动导入web环境所需要的所有依赖

主程序.
注解:.
1、表面理解:
@SpringBootApplication—— 启动类标志

2、接下来深入理解
进入
@SpringBootApplication注解内部可以看到其内部又包含了3个注解,与配置有关的就是@SpringBootConfiguration、@EnableAutoConfiguration

3、这两注解内部结构基本如下:
@SpringBootConfiguration
@Configuration // 说明 这个类是一个配置类(类似于Spring中xml配置文件)
@Component // 说明 这个类也是一个组件 -- 因此 可以被上面@ComponentScan扫描到
@EnableAutoConfiguration // 自动配置
@AutoConfigurationPackage // 自动配置包
@Import(AutoConfigurationPackages.Registrar.class) // 自动配置包注册
@Import(AutoConfigurationImportSelector.class) // 自动配置导入选择:获取所有的配置
4、看到以上结构,我们知道SpringBoot的自动配置,目前只涉及到两个类
AutoConfigurationPackages.Registrar : 包注册
Registrar.class 作用:将主启动类的所在包及包下面所有子包里面的所有组件扫描到Spring容器
AutoConfigurationImportSelector :导入候选的配置类 (重点)
一

AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
二

List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
三

四
加载了 EnableAutoConfiguration 对应的配置类 – 详情看后面 (META-INF/spring.facotories中对应的)

// 核心语句
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
getBeanClassLoader());


以下是可以被导入的配置类,如果没有,那么需要自定义配置


可以得出结论:所有的自动配置类都是在启动的时候被扫描并导入到容器(spring.factories中的自动配置类—— 全限定名形式 xxxAutoConfiguration),但是并不是都生效,看是否有对应的启动器(会涉及到新的注解)
①启动时,加载 spring.factories文件中的 自动配置类,导入到容器中
②当然,需要对应的启动器才生效
③xxxAutoConfIguration会导入其相关的组件(@Bean),并自动配置,免去我们手动编写的配置文件的工作
5、从以上我们知道了自动加载的配置类有哪些,但是实际上,并没有全部有效,为什么呢?
那么就涉及到 新的注解
@ConditionalXXX满足某些条件就加载,比如说有某个类(一般在启动器中)的时候生效
运行 Run.

查看构造器,SpringApplication做了如下4个事情:
- 推断应用的类型是普通还是Web
- 查找所有的应用程序监听器,设置到initializers属性中
- 找出所有的应用程序监听器,设置到listeners属性中
- 推断并设置main方法的定义类,找到运行的主类
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
this.webApplicationType = WebApplicationType.deduceFromClasspath();
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}
run方法流程分析.
该图来自狂神说Java,https://blog.csdn.net/qq_33369905/article/details/106647293

public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
configureHeadlessProperty();
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
configureIgnoreBeanInfo(environment);
Banner printedBanner = printBanner(environment);
context = createApplicationContext();
exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
refreshContext(context);
afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}
listeners.started(context);
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
try {
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
return context;
}