首先我们先看下核心文件
1.pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.7.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.qiu</groupId>
<artifactId>springboot-01-helloworld</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot-01-helloworld</name>
<description>qiu first springboot project</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
先挑出第一个来细讲:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.7.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
点进去看源码:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.2.7.RELEASE</version>
<relativePath>../../spring-boot-dependencies</relativePath>
</parent>
结果又来了一个parent,这个时候我们再点进去看
终于没有了
再往下滑动会发现:
这里管理存放着大量的jar包.
所以说pom.xml里
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starterartifactId>
dependency>`
启动器:说白了就是springboot的启动场景
starter
package com.qiu;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Springboot01HelloworldApplication {
public static void main(String[] args) {
SpringApplication.run(Springboot01HelloworldApplication.class, args);
}
}
先看主程序的注解:
@SpringBootApplication:标注这个类是一个springboot的应用
SpringApplication.run:将springboot的应用启动
@SpringBootConfiguration:springboot的配置
@Configuration:spring配置类:说明启动类也是一个配置类
然后在点进去:
@Component:说明这也是一个spring的组件
@EnableAutoConfiguration:自动配置
点击源码进去:
@AutoConfigurationPackage:自动配置包:自动配置包注册
@Import(AutoConfigurationImportSelector.class):自动导入选择
再点进去:
这个类中的一段代码如下:获取所有的配置
List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes)
getCandidateConfigurations:或者候选的配置
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
但是不一定生效,要判断条件是否成立,只要导入了对应的start,就有了对应的启动器,有了启动器,我们的自动装配,就会生效,然后就配置成功了
步骤:
6.容器中也会存在非常多的XXXAutoConfiguration的文件,就是这些类给容器中导入这些场景需要的所有的组件,并自动配置@Configuration,javaConfig
7. 有了自动配置类,免去了我们手动编写配置文件的工作
问题:
我们都知道:spring.factories这个文件中有所有的配置类,为什么这么多配置类中有的文件没有生效,而需要导入对应的start才能起作用?
核心注解@ConditionOn XXX :如果这里面的条件都满足才会生效!
比如说会判断jar包存不存在,如果不存在则所相对应的类就不会生效,所以说就算遍历了全部的配置类,但也不是说一定都有用.
上面一大串都是在将关于注解里面的,但是在主程序中不止是注解,他还有一个SpringApplication类,还有一个run方法
首先:springAppllication:
这个类主要做了以下四件事情:
1、推断应用的类型是普通的项目还是Web项目
2、查找并加载所有可用初始化器 , 设置到initializers属性中
3、找出所有的应用程序监听器,设置到listeners属性中
4、推断并设置main方法的定义类,找到运行的主类
查看构造器:
public SpringApplication(ResourceLoader resourceLoader, Class... primarySources) {
// ......
this.webApplicationType = WebApplicationType.deduceFromClasspath();
this.setInitializers(this.getSpringFactoriesInstances();
this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = this.deduceMainApplicationClass();
}