SpringBoot最大特点:自动装配
pom.xml
-
spring-boot-dependencies: 核心依赖都在父工程中定义好了,通过spring-boot-starter-parent进去。
我们中写或者引入springBoot依赖的时候,不需要写版本号,因为里面已经有了
启动器
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-........</artifactId>
</dependency>
- 启动器:就是SpringBoot的启动场景,比如数据库连接,消息队列等等
注解
@SpringBootApplication//springboot启动注解,启动类下面所有的资源被导入,下面有很多子注解
@SpringBootConfiguration//SpringBoot配置注解
@ComponentScan//包扫描注解,扫描同级及其下面的包注入到应用中
@EnableAutoConfiguration//启用自动配置注解---重要
@AutoConfigurationPackage//自动配置包
@Import({AutoConfigurationImportSelector.class})//导入AutoConfigurationImportSelector类(自动配置选择类)----重要
AutoConfigurationImportSelector
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!this.isEnabled(annotationMetadata)) {
return NO_IMPORTS;
} else {
//获取自动配置实体类
AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
}
//获取自动配置实体类
protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!this.isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
} else {
AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
//通过配置文件获取所有的start启动器,返回一个集合(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非常重要:里面告诉了我们所有的可以自动配置的类。当然我们也可以从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()) {//有没有更多的子节点
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);
}
}
}
结论: springboot所有自动配置都是在启动的时候加载: spring.factories所有的自动配置类都在这里
面,但是不一定生效,要判断条件是否成立,只要导入了对应的start,就有对应的启动器了,有了启动器,我们自动装配就会生效,然后就配置成功!
- springboot在启动的时候,从类路径下/META-INF/ spring . factories获取指定的值;
2.将这些自动配置的类导入容器,自动配置就会生效,帮我进行自动配置!
3.以前我们需要自动配置的东西,现在springboot帮我们做了!
4.整合javaEE,解决方案和自动配置的东西都在spring-boot-autoconfigure-2.2.0.RELEASE.jar这个包下
5.它会把所有需要导入的组件,以类名的方式返回,这些组件就会被添加到容器;
6.容器中也会存在非常多的xxAutoConfiguration的文件(@Bean),就是这些类给容器中导入了这个场景需要
的所有组件;并自动配置,@Configuration
7.有了自动配置类,免去了我们手动编写配置文件的工作
SpringApplication.run
1.推断应用的类型是普通的项目还是Web项目
2.查找并加载所有可用初始化器,设置到initializers属性中
3.找出所有的应用程序监听器,设置到listeners属性中
4.推断并设置main方法的定义类,找到运行的主类