首先我們先看下核心文件
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裏
- spring-boot-dependencies:核心依賴在父工程中
所以說這就是爲什麼不用寫版本號的原因,因爲上面的父工程已經管理了,有這些管理倉庫了.
2.啓動器
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>`
啓動器:說白了就是springboot的啓動場景
- 比如說spring-boot-starter-web,他就會幫我們自動導入web環境下所有的依賴
- springboot會將所有的功能場景會變成一個個啓動器
- 我們要使用什麼功能就只需要找到對應的啓動器就好了
starter
- 然後就是主程序了:
3.主程序
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,就有了對應的啓動器,有了啓動器,我們的自動裝配,就會生效,然後就配置成功了
步驟:
- springboot在啓動的時候,從類路徑下/META-INF/spring.factories獲取指定的值
- 將這些自動配置的類導入容器,自動配置類就會生效,幫我們自動配置
- 以前我們需要自動配置的東西,現在springboot幫我們做了
- 整個javaEE,解決方案和自動配置的東西都在 spring-boot-autoconfigure-2.2.7.RELEASE.jar裏面
- 它會把所有需要導入的組件,以類名的方式返回,這些組件就會被添加到容器
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();
}