springboot是服務於spring框架的框架,可以幫助使用Spring的開發者快速構建Spring框架,它基於了約定由於配置的理念,服務的範圍是簡化配置文件;
1.約定由於配置:
約定優於配置,是一種軟件設計範式,目的在於減少開發人員需要做決定的數量,使開發變得簡單,但不失靈活
體現:
- maven的目錄結構
- 默認以jar的方式打包
- 默認會有resource文件夾
- 默認提供application.properties/yml文件
- main方法運行就會啓動web工程,啓動時創建一個內置的tomcat容器,將當前項目部署在此容器中
- 可以通過Spring,profiles.active屬性來決定運行不同環境讀取的配置文件
- maven裏面引用了spring-boot-starter-web
- 會自動添加spring mvc工程所需要的所有東西
2. 重點需要了解的內容
對spring 已有的東西進行封裝然後創建出來的新東西:
- AutoConfiguration 自動裝配
- Starter
- Actuator
- SpringBoot CLI
3.啓動類上的複合註解: @SpringBootApplication
本質上覆合了@EnableAutoConfiguration,@ComponentScan,@Configuration
- EnableAutoC onfiguration
EnableAutoConfiguration 的 主要作用其實就是幫助springboot 應用把所有符合條件的@Configuration 配置都自動加載到當前 SpringBoot 創建並使用的 IOC 容器中 - ComponentScan
掃描@Component/@Reponsitory/@Service/@Controller 攜帶了上面註解的類都會被掃描到IOC容器內託管 - Configuration
任何一個標註了@Configuration 的 Java 類定義都是一個JavaConfig 配置類。而在這個配置類中,任何標註了@Bean 的方法,它的返回值都會作爲 Bean 定義註冊到Spring 的 IOC 容器,方法名默認成爲這個 bean 的 id;
4. Spring Boot 自動配置原理是什麼?
- 在複合註解SpringBootapplication中,包含EnableAutoConfiguration啓動spring應用程序上下文的自動配置,EnableAutoConfiguration內會導入一個AutoConfigurationImportSelector類詳細流程是這樣:
(1)SpringApplication.run(AppConfig.class,args);執行流程,中有refreshContext(context);
(2)refreshContext(context);內部會解析我們的配置類上的標籤.實現自動裝配功能的註解@EnableAutoConfiguration
(3)會解析@EnableAutoConfiguration這個註解裏面的@Import引入的配置類.AutoConfigurationImportSelector - 這個類會去讀取spring.factories下key爲EnableAutoConfiguration對應的全限定名的值;
- spring.factories裏配置的所有key-value,是要告訴springBoot這個stareter所需要加載的XXXAutoConfiguraion類,也就是我們想要自動注入的bean;
下的getCandidateConfigurations()
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
// 核心代碼
// 調用了方法:spring.core中的loadFactoryNames()
// 參數1--this.getSpringFactoriesLoaderFactoryClass()
// 參數2--this.getBeanClassLoader()
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.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;
}
- 參數1–this.getSpringFactoriesLoaderFactoryClass()
protected Class<?> getSpringFactoriesLoaderFactoryClass() {
return EnableAutoConfiguration.class;
}
- 參數2–this.getBeanClassLoader()
protected ClassLoader getBeanClassLoader() {
return this.beanClassLoader;
}
- org.springframework.core.io.support.SpringFactoriesLoader類下的loadFactoryNames()
public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) {
String factoryClassName = factoryClass.getName();
return (List)loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());
}
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
MultiValueMap<String, String> result = (MultiValueMap)cache.get(classLoader);
if (result != null) {
return result;
} else {
try {
// 核心代碼看這裏
Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");
LinkedMultiValueMap result = new LinkedMultiValueMap();
while(urls.hasMoreElements()) {
URL url = (URL)urls.nextElement();
UrlResource resource = new UrlResource(url);
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
Iterator var6 = properties.entrySet().iterator();
while(var6.hasNext()) {
Entry<?, ?> entry = (Entry)var6.next();
String factoryClassName = ((String)entry.getKey()).trim();
String[] var9 = StringUtils.commaDelimitedListToStringArray((String)entry.getValue());
int var10 = var9.length;
for(int var11 = 0; var11 < var10; ++var11) {
String factoryName = var9[var11];
result.add(factoryClassName, factoryName.trim());
}
}
}
cache.put(classLoader, result);
return result;
} catch (IOException var13) {
throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var13);
}
}
}
5. SPI擴展點機制的實現和運用
Spring的SPI是什麼?
SPI的全名爲Service Provider Interface,爲某個接口尋找服務實現的機制,也叫擴展點機制,主要是爲了提升擴展性而存在;
當服務的提供者,提供了服務接口的一種實現之後,在jar包的META-INF/services/目錄裏同時創建一個以服務接口命名的文件。該文件裏就是實現該服務接口的具體實現類。而當外部程序裝配這個模塊的時候,就能通過該jar包META-INF/services/裏的配置文件找到具體的實現類名,並裝載實例化,完成模塊的注入。通過這個約定,就不需要把服務放在代碼中了,通過模塊被裝配的時候就可以發現服務類了
場景:
當SpringBoot裏面提供了默認實現不滿足我們的要求時候,我們可以對其進行擴展添加自己的實現
過程:
在resource/META-INFO下添加spring.fatories文件,配置相應的key,value
key:類的全路徑(固定的 )
value對應着所有的實現