一、注解
@SpringBootApplication:标准这是一个springboot的应用,启动类下的所有资源将被导入
@SpringBootConfiguration:springboot的配置类
@ComponentScan:扫描当前主启动类下的所有包
@Configuration:spring配置类
@Component:说明这也是一个spring组件
@EnableAutoConfiguration:自动配置
@AutoConfigurationPackage:自动配置包
@Import(AutoConfigurationPackages.Registrar.class):自动配置‘包注册’
@Import(AutoConfigurationImportSelector.class):自动配置导入选择
//获取所有的配置
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
获取候选的配置
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
getBeanClassLoader());
Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you "
+ "are using a custom packaging, make sure that file is correct.");
return configurations;
}
META-INF/spring.factories:自动配置的核心文件
Properties properties = PropertiesLoaderUtils.loadProperties(resource);//加载所有资源
springboot所有的自动配置都是启动的时候扫描并加载:spring.factories:所有的配置类都在这里面,但不是所有的配置都生效。要判断条件是否都满足(@ConditionalOnxxx),只要导入了对应的start,就有了对应的启动器,有了启动器,自动装配就会生效,然后配置成功
自动配置
spring.factories文件中的xxxAutoConfiguration
xxxAutoConfiguration有一个默认值 或者进行配置xxxProperties
xxxProperties又和我们的配置文件绑定(application.yml)我们就可以进行自定义配置了
@ConfigurationProperties(prefix = "server", ignoreUnknownFields = true)
- springboot在启动时会加载大量的自动配置类
spring.factories文件中的xxxAutoConfiguration
- 我们看我们需要的功能有没有在springboot默认写好的自动配置类中
- 我们再来看这个自动配置类写了哪些组件;(只要我们需要的在里面,我们就不需要再手动配置了)
- 给容器中的自动配置类添加组件的时候,会从Properties类中获取某些属性,我们只要在配置文件中,指定这些属性值即可
**xxxAutoConfiguration 自动配置类;**给容器添加组件
xxxProperties:封装配置文件的相关属性
主启动类运行分析
SpringApplication
做了四件事
- 推断类是普通项目还是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();
}
private Class<?> deduceMainApplicationClass() {
try {
StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();
for (StackTraceElement stackTraceElement : stackTrace) {
if ("main".equals(stackTraceElement.getMethodName())) {
return Class.forName(stackTraceElement.getClassName());
}
}
}
catch (ClassNotFoundException ex) {
// Swallow and continue
}
return null;
}