SpringBoot最大特點(diǎn):自動裝配
pom.xml
-
spring-boot-dependencies: 核心依賴都在父工程中定義好了荆残,通過spring-boot-starter-parent進(jìn)去鸵赖。
我們中寫或者引入springBoot依賴的時(shí)候渊额,不需要寫版本號尽纽,因?yàn)槔锩嬉呀?jīng)有了
spring-boot-starter-parent
啟動器
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-........</artifactId>
</dependency>
- 啟動器:就是SpringBoot的啟動場景,比如數(shù)據(jù)庫連接乃坤,消息隊(duì)列等等
注解
@SpringBootApplication//springboot啟動注解苛让,啟動類下面所有的資源被導(dǎo)入,下面有很多子注解
@SpringBootConfiguration//SpringBoot配置注解
@ComponentScan//包掃描注解湿诊,掃描同級及其下面的包注入到應(yīng)用中
@EnableAutoConfiguration//啟用自動配置注解---重要
@AutoConfigurationPackage//自動配置包
@Import({AutoConfigurationImportSelector.class})//導(dǎo)入AutoConfigurationImportSelector類(自動配置選擇類)----重要
AutoConfigurationImportSelector
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!this.isEnabled(annotationMetadata)) {
return NO_IMPORTS;
} else {
//獲取自動配置實(shí)體類
AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
}
//獲取自動配置實(shí)體類
protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!this.isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
} else {
AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
//通過配置文件獲取所有的start啟動器狱杰,返回一個(gè)集合(getCandidateConfigurations)
List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
configurations = this.removeDuplicates(configurations);
Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
this.checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = this.getConfigurationClassFilter().filter(configurations);
this.fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);
}
}
//從字面意思就是獲取獲取候選配置
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
//通過類名加載自動注入
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
//如果為null,就返回提示厅须,在META-INF / spring.factories中找不到自動配置類仿畸。 如果您使用的是自定義包裝,請確保該文件正確無誤九杂。這就告訴我們 spring.factories非常重要:里面告訴了我們所有的可以自動配置的類颁湖。當(dāng)然我們也可以從loadFactoryNames()方法中的loadSpringFactories()方法知道是從spring.factories匹配類名,然后加載出來的
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;
}
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
ClassLoader classLoaderToUse = classLoader;
if (classLoader == null) {
classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
}
String factoryTypeName = factoryType.getName();
return (List)loadSpringFactories(classLoaderToUse).getOrDefault(factoryTypeName, Collections.emptyList());
}
private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) {
Map<String, List<String>> result = (Map)cache.get(classLoader);
if (result != null) {
return result;
} else {
HashMap result = new HashMap();
try {
//獲取資源目錄下面META-INF/spring.factories所有的url
Enumeration urls = classLoader.getResources("META-INF/spring.factories");
while(urls.hasMoreElements()) {//有沒有更多的子節(jié)點(diǎn)
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 factoryTypeName = ((String)entry.getKey()).trim();
String[] factoryImplementationNames = StringUtils.commaDelimitedListToStringArray((String)entry.getValue());
String[] var10 = factoryImplementationNames;
int var11 = factoryImplementationNames.length;
for(int var12 = 0; var12 < var11; ++var12) {
String factoryImplementationName = var10[var12];
((List)result.computeIfAbsent(factoryTypeName, (key) -> {
return new ArrayList();
})).add(factoryImplementationName.trim());
}
}
}
result.replaceAll((factoryType, implementations) -> {
return (List)implementations.stream().distinct().collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList));
});
//放入到緩存中
cache.put(classLoader, result);
return result;
} catch (IOException var14) {
throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var14);
}
}
}
結(jié)論: springboot所有自動配置都是在啟動的時(shí)候加載: spring.factories所有的自動配置類都在這里
面例隆,但是不一定生效,要判斷條件是否成立甥捺,只要導(dǎo)入了對應(yīng)的start,就有對應(yīng)的啟動器了镀层,有了啟動器镰禾,我們自動裝配就會生效,然后就配置成功!
- springboot在啟動的時(shí)候唱逢,從類路徑下/META-INF/ spring . factories獲取指定的值;
2.將這些自動配置的類導(dǎo)入容器吴侦,自動配置就會生效,幫我進(jìn)行自動配置!
3.以前我們需要自動配置的東西,現(xiàn)在springboot幫我們做了!
4.整合javaEE,解決方案和自動配置的東西都在spring-boot-autoconfigure-2.2.0.RELEASE.jar這個(gè)包下
5.它會把所有需要導(dǎo)入的組件坞古,以類名的方式返回备韧,這些組件就會被添加到容器;
6.容器中也會存在非常多的xxAutoConfiguration的文件(@Bean),就是這些類給容器中導(dǎo)入了這個(gè)場景需要
的所有組件;并自動配置,@Configuration
7.有了自動配置類痪枫,免去了我們手動編寫配置文件的工作
SpringApplication.run
1.推斷應(yīng)用的類型是普通的項(xiàng)目還是Web項(xiàng)目
2.查找并加載所有可用初始化器织堂,設(shè)置到initializers屬性中
3.找出所有的應(yīng)用程序監(jiān)聽器,設(shè)置到listeners屬性中
4.推斷并設(shè)置main方法的定義類奶陈,找到運(yùn)行的主類