3. SpringBoot ——自动配置原理浅析
SpringBoot的功能之所以强大,离不开它的自动配置这一大特色。但估计很多人只是知其然而不知其所以然。下面本人对自动配置原理做一个分析:
在使用SpringBoot时我们通过引入不同的Starter,就自动地应用其相应的自动配置。这是由于每个Starter都会引一个相应xxx--autoconfigure.jar,并且在这个jar的META-INF/spring.factories文件中有类似如下的配置:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration
也就是通过org.springframework.boot.autoconfigure.EnableAutoConfiguration这个为 key引入自动配置类。这个自动类就会以代码的方式去完成以前Spring的xml配置文件做的事。
现在的关键问题就是,Spring的容器是如何知道这个自动配置类的存在的呢?带着这个问题,我们来跟踪SpringBoot启动类的实例run方法,先列出方法源码:
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
FailureAnalyzers analyzers = null;
configureHeadlessProperty();
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args);
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
Banner printedBanner = printBanner(environment);
context = createApplicationContext();
analyzers = new FailureAnalyzers(context);
prepareContext(context, environment, listeners, applicationArguments,
printedBanner);
refreshContext(context);
afterRefresh(context, applicationArguments);
listeners.finished(context, null);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass)
.logStarted(getApplicationLog(), stopWatch);
}
return context;
}
catch (Throwable ex) {
handleRunFailure(context, listeners, analyzers, ex);
throw new IllegalStateException(ex);
}
}
其实整个过程的秘密全在上面这段代码中体现出来了,只不过隐藏的比较深而已。上面这段有两个方法是和Spring容器发现这个自动配置类有关的
1. 在这个 prepareContext(context, environment, listeners, applicationArguments,printedBanner)
方法中完成了SpringBoot 的main方法中的启动类在Spring容器中的注册,并且是以源的方式进行注册。也就是相当于告诉spring容器,这个启动类就相当于是以前的xml文件了
2. refreshContext(context);
这个就是初始化 Spring容器,并实例化容器中注册的Bean,自然也就会对SpringBoot 的main方法中的启动类进行解析,这样一来,启动类上的 注解 @EnableAutoConfiguration就起作用了,但是要注意@EnableAutoConfiguration注解是springBoot提供的,springframeworke中的ApplicationContext是不会理会它的,而springboot接管后,相应的容器也是springBoot提供的,所以@EnableAutoConfiguration注解才会起作用,在createApplicationContext()中能看到springboot使用的容器类。
protected ConfigurableApplicationContext createApplicationContext() {
Class<?> contextClass = this.applicationContextClass;
if (contextClass == null) {
try {
switch (this.webApplicationType) {
case SERVLET:
contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);
break;
case REACTIVE:
contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
break;
default:
contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
}
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Unable create a default ApplicationContext, "
+ "please specify an ApplicationContextClass",
ex);
}
}
return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
}
下面看 @EnableAutoConfiguration的源码:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration { String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration"; /**
* Exclude specific auto-configuration classes such that they will never be applied.
* @return the classes to exclude
*/
Class<?>[] exclude() default {}; /**
* Exclude specific auto-configuration class names such that they will never be
* applied.
* @return the class names to exclude
* @since 1.3.0
*/
String[] excludeName() default {}; }
会发现这个 @EnableAutoConfiguration 注解里面 @Import(AutoConfigurationImportSelector.class)
AutoConfigurationImportSelector里面有几段代码说明其会从META-INF/spring.factories文件,并加载其中配置key为org.springframework.boot.autoconfigure.EnableAutoConfiguration对应的类,我们称之为自动配置类,这样类上都会有@Configuration注解,所以就能被spring容器处理了。
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
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.");
return configurations;
} /**
* Return the class used by {@link SpringFactoriesLoader} to load configuration
* candidates.
* @return the factory class
*/
protected Class<?> getSpringFactoriesLoaderFactoryClass() {
return EnableAutoConfiguration.class;
}
总结:
@SpringBootApplication —— > @EnableAutoConfiguration ——> AutoConfigurationImportSelector——>META-INF/spring.factories
至此,一切真相大白。
3. SpringBoot ——自动配置原理浅析的更多相关文章
- 这样讲 SpringBoot 自动配置原理,你应该能明白了吧
https://juejin.im/post/5ce5effb6fb9a07f0b039a14 前言 小伙伴们是否想起曾经被 SSM 整合支配的恐惧?相信很多小伙伴都是有过这样的经历的,一大堆配置问题 ...
- springboot自动配置原理以及手动实现配置类
springboot自动配置原理以及手动实现配置类 1.原理 spring有一个思想是"约定大于配置". 配置类自动配置可以帮助开发人员更加专注于业务逻辑开发,springboot ...
- SpringBoot自动配置原理
前言 只有光头才能变强. 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y 回顾前面Spring的文章(以学习的顺序排好): S ...
- SpringBoot实战之SpringBoot自动配置原理
SpringBoot 自动配置主要通过 @EnableAutoConfiguration, @Conditional, @EnableConfigurationProperties 或者 @Confi ...
- SpringBoot自动配置原理学习
介绍 构建Springboot项目时我们会创建一个启动类 @SpringBootApplication public class DemoApplication { public static voi ...
- 浅谈springboot自动配置原理
前言 springboot自动配置关键在于@SpringBootApplication注解,启动类之所以作为项目启动的入口,也是因为该注解,下面浅谈下这个注解的作用和实现原理 @SpringBootA ...
- SpringBoot系列二:SpringBoot自动配置原理
主程序类的注解 @SpringBootApplication 注解,它其实是个组合注解,源码如下: @Target({ElementType.TYPE}) @Retention(RetentionPo ...
- springBoot 自动配置原理--自己新建一个 starter
上篇我们说到 springboot 和 SSM 框架的区别,今天我们就看看 springboot 到底为我们做了哪些事情,让我们开发变得如此简单. springboot 中起着重要作用的是 start ...
- springBoot 自动配置原理
在之前文章中说过,springBoot会根据jar包去添加许多的自动配置,本文就来说说为什么会自动配置,自动配置的原理时什么? springBoot在运行SpringApplication对象实例化时 ...
随机推荐
- Word 测试下发布博客
目录 语法. 3 NULL,TRUE,FALSE 3 大小端存储 4 类型转换 4 转义字符 5 运算符的优先级 5 表达式(a=b=c) 7 *pa++=* ...
- layui(八)——轮播图常见用法总结
carousel 是 layui 2.0 版本中新增的全新模块,主要适用于跑马灯/轮播等交互场景.它可以满足任何类型内容的轮播式切换操作,更可以胜任 FullPage (全屏上下轮播)的需求,简洁而不 ...
- [开源 .NET 跨平台 Crawler 数据采集 爬虫框架: DotnetSpider] 学习
http://www.cnblogs.com/jjg0519/p/6707513.html
- 解决Navicat 出错:1130-host . is not allowed to connect to this MySql server,MySQL
1. 改表法. 可能是你的帐号不允许从远程登陆,只能在localhost.这个时候只要在localhost的那台电脑,登入MySQL后,更改 "mysql" 数据库里的 " ...
- springcloud 服务调用的两种方式
spring-cloud调用服务有两种方式,一种是Ribbon+RestTemplate, 另外一种是Feign.Ribbon是一个基于HTTP和TCP客户端的负载均衡器,其实feign也使用了rib ...
- HDU 6400(括号组合 ~)
题意是说在 h 行 w 列的矩阵中,通过设计使得尽可能多的行或列能满足题中的平衡条件. 如果行数(列数)是奇数,那么每一列(行)一定不能平衡,就要按照满足每一行(列)平衡,输出“ () “:若行数和列 ...
- iOS下如何阻止橡皮筋效果
$(document).ready(function(){ var stopScrolling = function(event) { event.preventDefault(); } docume ...
- jsp查询修改
也是只帖代码....不讲解. 1.search.jsp <%@ page language="java" import="java.util.*" pag ...
- SQL Server进阶(四):联接-cross join、inner join、left join、right jion、union、union all
测试数据脚本 CREATE TABLE Atable ( S# INT, Sname ), Sage INT, Sfrom ) ) insert into Atable ,N,N'A' union a ...
- Immunity Debugger学习
1.Immunity Debugger简介 Immunity Debugger软件专门用于加速漏洞利用程序的开发,辅助漏洞挖掘以及恶意软件分析.它具备一个完整的图形用户界面,同时还配备了迄今为止最为强 ...