启动器:

spring-boot-starter:spring-boot场景启动器,帮我们倒入我们场景需要的组件依赖

不同的场景有不同的启动器:

spring-boot-starter-web  
 
 
主程序类,主入口类:
 
@SpringBootApplication
public class DoneApplication { public static void main(String[] args) {
SpringApplication.run(DoneApplication.class, args);
}
}
@SpringBootApplication:    Spring Boot应用标注在某个类上说明这个类是SpringBoot的主配置类,
SpringBoot就应该运行这个类的main方法来启动SpringBoot应用;

这个注解的详如下:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
excludeFilters = {@Filter(
type = FilterType.CUSTOM,
classes = {TypeExcludeFilter.class}
), @Filter(
type = FilterType.CUSTOM,
classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
@SpringBootConfiguration  springboot的配置类的注解,标注在某个类上,表示这是一个Spring Boot的配置类
@EnableAutoConfiguration  开启自动配置,告诉SpringBoot开启自动配置功能,详解如下:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
@AutoConfigurationPackage:自动配置包
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import({Registrar.class})
public @interface AutoConfigurationPackage {

@Import(Registrar.class):

Spring的底层注解@Import,给容器中导入一个组件;导入的组件由 Registrar.class;

将主配置类(@SpringBootApplication: 标注的类)的所在包及下面所有子包里面的所有组件扫描到容器

AutoConfigurationImportSelector 类的作用就是往 Spring 容器中导入组件,导入哪些组件的选择器

将所有需要导入的组件以全类名的方式返回;这些组件就会被添加到容器中;
会给容器中导入非常多的自动配置类(xxxAutoConfiguration);就是给容器中导入这个场景需要的所有组件, 并配置好这些组件;

流程;

@SpringbootApplication注解--@EnableAutoConfiguration--@Import(AutoConfigurationImportSelector.class)重要就是这个类

AutoConfigurationImportSelector这个类有个方法:

@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}

AutoConfigurationImportSelector 的 selectImports 就是用来返回需要导入的组件的全类名数组的

就是通过方法getAutoConfigurationEntry方法

getCandidateConfigurations方法里面

SpringFactoriesLoader里面函数loadFactoryNames

loadFactoryNames里面的

 public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
String factoryTypeName = factoryType.getName();
return (List)loadSpringFactories(classLoader).getOrDefault(factoryTypeName, 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 factoryTypeName = ((String)entry.getKey()).trim();
String[] var9 = StringUtils.commaDelimitedListToStringArray((String)entry.getValue());
int var10 = var9.length; for(int var11 = 0; var11 < var10; ++var11) {
String factoryImplementationName = var9[var11];
result.add(factoryTypeName, factoryImplementationName.trim());
}
}
} cache.put(classLoader, result);
return result;
} catch (IOException var13) {
throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var13);
}
}
}

1111获取配置文件信息:

 Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");

2222通过函数loadSpringFactories获取一个map集合:

private static Map<String, List<String>> loadSpringFactories

先寻找传入了什么

回到选择器:

333从返回的 Map 中通过刚才传入的 EnableAutoConfiguration.class 参数,获取该 key 下的所有值。

 

 
 
 
 
 
 
 
 
 
 
 

spring-boot-learning自动配置原理的更多相关文章

  1. Spring Boot的自动配置原理及启动流程源码分析

    概述 Spring Boot 应用目前应该是 Java 中用得最多的框架了吧.其中 Spring Boot 最具特点之一就是自动配置,基于Spring Boot 的自动配置,我们可以很快集成某个模块, ...

  2. Spring boot 的自动配置

    Xml 配置文件 日志 Spring Boot对各种日志框架都做了支持,我们可以通过配置来修改默认的日志的配置: #设置日志级别 logging.level.org.springframework=D ...

  3. spring boot(12)-数据源配置原理

    本篇讲的不仅是数据源配置,这也是spring boot实现自动配置的一部分.要理解数据源的配置原理,首先要理解第十篇tomcat连接池的配置 数据源配置源码 这里截取org.springframewo ...

  4. 了解Spring Boot的自动配置

    摘自:https://www.jianshu.com/p/ddb6e32e3faf Spring Boot的自动配置给开发者带来了很大的便利,当开发人员在pom文件中添加starter依赖后,mave ...

  5. Spring Boot的自动配置

    Spring Boot的自动配置 --摘自https://www.hollischuang.com/archives/1791 随着Ruby.Groovy等动态语言的流行,相比较之下Java的开发显得 ...

  6. 初识Spring Boot框架(二)之DIY一个Spring Boot的自动配置

    在上篇博客初识Spring Boot框架中我们初步见识了SpringBoot的方便之处,很多小伙伴可能也会好奇这个Spring Boot是怎么实现自动配置的,那么今天我就带小伙伴我们自己来实现一个简单 ...

  7. spring boot 系列之六:深入理解spring boot的自动配置

    我们知道,spring boot自动配置功能可以根据不同情况来决定spring配置应该用哪个,不应该用哪个,举个例子: Spring的JdbcTemplate是不是在Classpath里面?如果是,并 ...

  8. Spring Boot 排除自动配置的 4 种方法,关键时刻很有用!

    Spring Boot 提供的自动配置非常强大,某些情况下,自动配置的功能可能不符合我们的需求,需要我们自定义配置,这个时候就需要排除/禁用 Spring Boot 某些类的自动化配置了. 比如:数据 ...

  9. 自定义spring boot的自动配置

    文章目录 添加Maven依赖 创建自定义 Auto-Configuration 添加Class Conditions 添加 bean Conditions Property Conditions Re ...

  10. Spring Boot的自动配置的原理浅析

    一.原理描述 Spring Boot在进行SpringApplication对象实例化时会加载META-INF/spring.factories文件,将该配置文件中的配置载入到Spring容器. 二. ...

随机推荐

  1. PentestBOX教程

    0x01 Pentest BOX Pentest Box:渗透测试盒子,是一款Windows平台下预配置的便携式开源渗透测试环境,而它也是著名黑客Kapustkiy常用的工具之一.这里集成的大都是Li ...

  2. Install VMware Tools in CentOS 7 command line mode

    1.首先启动CentOS 7,在VMware中点击上方"VM",点击"Install VMware Tools..."(如已安装则显示"Reinsta ...

  3. 关于linux下,ls vi等命令失效的解决方法(配置下环境变量出现问题)

    转至:https://www.cnblogs.com/afeiiii/p/13824530.html 配置完环境变量source之后,linux的ls vi命令均失效,报错如下: 解决方法 1.输入  ...

  4. nodejs调用jar

    目前nodejs调用jar主要有两种方式: 通过创建子进程运行java -jar命令调用包含main方法的jar 使用node-java通过c++桥接调用jar 方法一(子进程运行): const { ...

  5. C语言刷2数/3数/4数之和

    15. 三数之和 /** * Return an array of arrays of size *returnSize. * The sizes of the arrays are returned ...

  6. 快速整透Redis中的压缩列表到底是个啥

    压缩列表简介 压缩列表(ziplist)是由一个连续内存组成的顺序型数据结构.一个压缩列表可以包含任意多个节点,每个节点上可以保存一个字节数组或整数值.它是Redis为了节省内存空间而开发的. 压缩列 ...

  7. js数组和对象的区别,ajax传入多个参数值,ajax传多个数组数据

    数组分为索引数组和关联数组 js中先声明一个空数组 arr = [] 索引数组 索引是整数,如arr[0] = 'a' 关联数组 索引是自定义的字符串,如arr['a'] = 'a' js中的对象 你 ...

  8. 从零开始,开发一个 Web Office 套件(9):拖动鼠标选中文字 Edge Case

    这是一个系列博客,最终目的是要做一个基于 HTML Canvas 的.类似于微软 Office 的 Web Office 套件(包括:文档.表格.幻灯片--等等). 博客园:<从零开始, 开发一 ...

  9. 使用Vscode和Cmake打造跨平台的C++ IDE

    准备工作 Viusal Studio Code 64位 :Download Visual Studio Code - Mac, Linux, Windows Cmake 3.4 :Download | ...

  10. CF678F题解

    首先题意中的有撤销操作,直接李超树肯定不行,题目允许离线,所以考虑线段树分治 所以问题就变成了求一次函数最大值 这不是李超树板子吗??? 然后可以对每个节点都建立动态开点李超树,查询的时候直接从叶子节 ...