SpringBoot(三)SpringBoot自动配置
我们都知道SpringBoot帮助我们集成了许多组件和配置,那么SpringBoot是如何集成这些配置并在启动是自动进行配置呢。说到这就不得又需要回过头来看一下@SpringBootApplication这个注解了,之前已经说过这个注解是@Configuration,@EnableAutoConfiguration,@ComponentScan三个注解的组合,这里需要特殊强调下@EnableAutoConfiguration这个注解,没错就是这个注解使SpringBoot完成自动配置的。@EnableAutoConfiguration-----@Import(EnableAutoConfigurationImportSelector.class)-----AutoConfigurationImportSelector按照这个顺序我们可以进入SpringBoot的自动配置导入选择器。接下来我们就看一下SpringBoot是如何完成自动配置并观摩下源码。
public String[] selectImports(AnnotationMetadata annotationMetadata) { //进行选择导入
if (!isEnabled(annotationMetadata)) { //判断原数据是否为空为空返回空不为空进行导入相关操作
return NO_IMPORTS;
}
try {
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
.loadMetadata(this.beanClassLoader);
AnnotationAttributes attributes = getAttributes(annotationMetadata); //加载并获取属性
List<String> configurations = getCandidateConfigurations(annotationMetadata, //获取配置信息
attributes);
configurations = removeDuplicates(configurations);
configurations = sort(configurations, autoConfigurationMetadata);
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
14 checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = filter(configurations, autoConfigurationMetadata); //从11行到16进行移除未完全集成的配置并进行排序和过滤
fireAutoConfigurationImportEvents(configurations, exclusions); //导入过滤后的组件
return configurations.toArray(new String[configurations.size()]);
}
catch (IOException ex) {
throw new IllegalStateException(ex);
}
}
上面代码是进行自动配置的主方法,其实操作流程我在注释上已经进行了简单的说明
1.先对原数据进行判断是否为空再进行具体操作
2.加载原数据并获取属性
3.获取配置信息 (其实最重要的就是第三点因为如何获取配置信息并进行加载才是我们最关心的也是SpringBoot中最核心的部分)
4.移除未完全集成的配置并进行排序过滤 (由于有些配置SpringBoot并没有给我们进行完全配置,需要我们自己进行手动配置,这里之所以这么做个人认为如果SpringBoot把所有的组件都进行集成那么对项目本身启动来说就会造成一定的压力,毕竟有些组件在有些项目中并不需要使用)
5.导入处理后的组件配置
这里我们需要着重强调下getCandidateConfigurations这个方法,看看SpringBoot是如何获取组件的。
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames( //Spring工厂进行加载获取配置信息
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."); //如果配置不为空返回配置信息否则说明在META-INF/spring.factories这个目录下没有找到配置信息
return configurations;
}
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) {
String factoryClassName = factoryClass.getName();
try {
Enumeration<URL> urls = (classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) : //获取资源路径
ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
List<String> result = new ArrayList<String>();
while (urls.hasMoreElements()) { //如果存在将资源存入结果集中
URL url = urls.nextElement();
Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));
String factoryClassNames = properties.getProperty(factoryClassName);
result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames)));
}
return result;
}
catch (IOException ex) {
throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() +
"] factories from location [" + FACTORIES_RESOURCE_LOCATION + "]", ex);
}
}


相信看到这里已经不需要我过多的说明了,简而言之就是SpringBoot会去"META-INF/spring.factories"目录中去获取配置信息,然后再去做自动配置,现在我们在回过头来看最初SpringBoot进行自动配置的方法,我们走debug看一下。

这里我们可以看到SpringBoot在没有进行移除和过滤之前他在目录中获取到了96个组件下面再看一下过滤之后的。

过滤之后还有20个,也就是说SpringBoot为我们完全集成并自动配置的有20个组件,如果需要其他组件我们自己进行手动配置。(版本不动支持的组件数量或许有变化这里我是用的是1.5.9的版本)
除了这种方式还有其他方式来确定SpringBoot为我们自动配置了哪些组件么?如果这样看的话确实麻烦了写毕竟我们不可能每次都要在启动的时候通过debug来确认哪些是否被自动配置了,SpringBoot提供了debug启动模式让我们在控制台中就可以看到哪些进行了自动配置哪些没有完成自动配置,话不多说上图



Positive matches: 已经自动配置的 Negative matches:没有自动配置,以上就是SpringBoot如何完成自动配置的,其实自动配置这块想了好久要不要写,毕竟SpringBoot核心的配置,也怕有些地方写错了会误导其他人,也希望看到这篇文章的,看到有错误的地方希望能指正出来,互相学习互相进步,我不是一个勤快的人,但我希望能够改变当前懒散的状态,直到现在还记的我大学老师的一句话,只要开始永远不晚,只要努力就会成功,或许有鸡汤的成分,但还是希望只要开始永远不晚。
在很长的一段时间我变的颓废混日子,甚至忘了当初选择这个行业的初衷,总是喜欢抱怨种种得不公,我希望以后的日子我能找回那个努力的自己,没有人愿意平平淡淡,碌碌无为过一生,不求无愧于他人,但求无愧于自己,也希望每个在这个行业里为之坚持的伙伴我们都能无愧于自己,成为那个想象中的自己。
SpringBoot(三)SpringBoot自动配置的更多相关文章
- Springboot学习03-SpringMVC自动配置
Springboot学习03-SpringMVC自动配置 前言 在SpringBoot官网对于SpringMVCde 自动配置介绍 1-原文介绍如下: Spring MVC Auto-configur ...
- 【玩转SpringBoot】给自动配置来个整体大揭秘
上一篇文章中提到的条件注解,只是自动配置整体解决方案中的一个环节而已,可以说是管中窥豹. 本文就逐步擦除迷雾,让整体浮现出来,这样就会有一个宏观的认识. 除了写代码之外,还能干点什么? 提到“配置”这 ...
- Springboot 禁用数据库自动配置
转载至:https://blog.csdn.net/wyw815514636/article/details/80846545 https://blog.csdn.net/knqi007/articl ...
- SpringBoot 系列教程自动配置选择生效
191214-SpringBoot 系列教程自动配置选择生效 写了这么久的 Spring 系列博文,发现了一个问题,之前所有的文章都是围绕的让一个东西生效:那么有没有反其道而行之的呢? 我们知道可以通 ...
- 【springboot】之自动配置原理
使用springboot开发web应用是很方便,只需要引入相对应的GAV就可以使用对应的功能,springboot默认会帮我们配置好一些常用配置.那么springboot是怎么做到的呢?这篇文章将一步 ...
- SpringBoot 三种方式配置 Druid(包括纯配置文件配置)
记录一下在项目中用纯 YML(application.yml 或者 application.properties)文件.Java 代码配置 Bean 和注解三种方式配置 Alibaba Druid 用 ...
- SpringBoot扩展SpringMVC自动配置
SpringBoot中自动配置了 ViewResolver(视图解析器) ContentNegotiatingViewResolver(组合所有的视图解析器) 自动配置了静态资源文件夹.静态首页.fa ...
- IntelliJ IDEA 2017版 SpringBoot的关闭自动配置和自定义Banner
一.关闭自动配置 在jar包下找下边的名字 设置关闭自动配置jar 多个的时候配置 二.自定义Banner (1)网站搜索一个图案.网址:http://patorjk.co ...
- SpringBoot日记——SpringMvc自动配置与扩展篇
为了让SpringBoot保持对SpringMVC的全面支持和扩展,而且还要维持SpringBoot不写xml配置的优势,我们需要添加一些简单的配置类即可实现: 通常我们使用的最多的注解是: @Bea ...
随机推荐
- centos7限制普通用户访问单一目录下的单一文件
要求给开发同事开设一个查看日志的账号,并限制其只能访问该目录下的单一文件 1.先新建账号 useradd loglook passwd loglook 家目录为/home/loglook 2.日志的属 ...
- Github 绑定域名添加https的方法 2019年9月更新
官方教程 https://help.github.com/en/articles/using-a-custom-domain-with-github-pages 打开 https://github.c ...
- 一文搞懂jvm内存结构
一.jvm是干什么的? 大家都知道java是跨平台语言,一次编译可以在不同操作系统上运行,怎么做到的呢,看下图: javac把写的源代码(java文件),编译成字节码(class文件),字节码部署到l ...
- Dubbo源码解析之SPI(一):扩展类的加载过程
Dubbo是一款开源的.高性能且轻量级的Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用.智能容错和负载均衡,以及服务自动注册和发现. Dubbo最早是阿里公司内部的RPC框架,于 ...
- Py基础之函数
'''函数是指一类同类事物的抽象,而且这种抽象可以拓展,并且可以用在同一类事物上'''print (abs(-100),abs(100)) #abs函数是python内置的函数,可以用来求绝对值#pr ...
- 原生js实现在表格用鼠标框选并有反选功能
今天应同学要求,需要写一个像Excel那样框选高亮,并且实现框选区域实现反选功能.要我用原生js写,由于没什么经验翻阅了很多资料,第一次写文章希望各位指出不足!! 上来先建表 <div clas ...
- 前端面试题-HTML语义化标签
一.HTML5语义化标签 标签 描述 <article> 页面独立的内容区域. <aside> 页面的侧边栏内容. <bdi> 允许您设置一段文本,使其脱离其父元素 ...
- Linux中软连接和硬连接的区别
首先,我们要清楚符号链接的目的,在不改变原目录/文件的前提下,起一个方便的别名(在这起个别名,让我想到前阶段学C里typedef也是起别名的). 1.软连接就相当于windows的快捷方式.例如:ln ...
- MySQL敏感数据加密及解密
大数据时代的到来,数据成为企业最重要的资产之一,数据加密的也是保护数据资产的重要手段.本文主要在结合学习通过MySQL函数及Python加密方法来演示数据加密的一些简单方式. 1. 准备工作 为了便于 ...
- 脚本写一行echo也能写出bug ? glob了解一下
背景 最近处理一个 bug 很有意思,有客户反馈某个配置文件解析失败了,出错的那行的内容就只有一个字母 a. 最开始以为是谁改动了处理的脚本,但要到了问题代码中的脚本,比较发现跟库上是一样的. 又经过 ...