springboot_自动配置原理
springboot啥都不难,总所周知spring全家桶系列难就难在理解源码。。。。。。。
今天结合网上资料,自己总结了一下springboot的自动配置原理。
我现在使用的springboot版本为2.3.1.不同版本的springboot在源码上有差别!但大体一致。
管他三七二十一先打个断点再说:
1.1 @SpringBootApplication
这个注解点进去我们可以看到:
这里面主要关注两个东西:
- @SpringBootConfiguration
- @EnableAutoConfiguration
第一个注解点进去:
可以看到这个@SpringBootConfiguration本质就是一个@Configuration,标注在某个类上,表示这是一个Spring Boot的配置类。
第二个注解@EnableAutoConfiguration: 开启自动配置类,SpringBoot的精华所在。(最重要的就是这个注解)
2.1 @EnableAutoConfiguration
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
Class<?>[] exclude() default {};
String[] excludeName() default {};
}
两个比较重要的注解:
- @AutoConfigurationPackage:自动配置包。
- @Import({AutoConfigurationImportSelector.class}):导入自动配置的组件。
2.1.1 @AutoConfigurationPackage
点进去瞅瞅:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import({Registrar.class})
public @interface AutoConfigurationPackage {
String[] basePackages() default {};
Class<?>[] basePackageClasses() default {};
}
发现这里有导入Regitstrar类:
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
Registrar() {
}
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
AutoConfigurationPackages.register(registry, (String[])(new AutoConfigurationPackages.PackageImports(metadata)).getPackageNames().toArray(new String[0]));
}
public Set<Object> determineImports(AnnotationMetadata metadata) {
return Collections.singleton(new AutoConfigurationPackages.PackageImports(metadata));
}
}
new PackageImport(metadata).getPackageName(),它其实返回了当前主程序类的 **同级以及子级 ** 的包组件。
什么意思呢?
我们来看这样一个目录:
bean1和我们的springboot启动类位于同一个包下,二bean2不是位于我们启动类的同级目录或者子级目录,那么我们启动的时候bean2是不会被加载到的!所以你项目的一切需要加入容器的类必须放在启动类的同级包下或者它的子级目录中。
2.1.2 @Import({Registrar.class})
AutoConfigurationImportSelector有一个方法为:selectImports。
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!this.isEnabled(annotationMetadata)) {
return NO_IMPORTS;
} else {
AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
}
它首先回去检查是否开启了自动配置类,然后才回去加载注解数据 this.getAutoConfigurationEntry(annotationMetadata);
那么这个annotationMetadata在哪儿?
来看下面一行代码:
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.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;
}
SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
再点进去我们会发现这一行代码:
Enumeration urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");
它其实是去加载 public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";外部文件。这个外部文件,有很多自动配置的类。如下:
spring.factories文件由一组一组的key=value的形式,其中一个key是EnableAutoConfiguration类的全类名,而它的value是一个xxxxAutoConfiguration的类名的列表,这些类名以逗号分隔。
springboot项目启动时,@SpringBootApplication用在启动类在SpringApplication.run(...)的内部就会执行selectImports()方法,找到所有JavaConfig自动配置类的全限定名对应的class,然后将所有自动配置类加载到Spring容器中。
3.1 以HttpEncodingAutoConfiguration为例
@Configuration(
proxyBeanMethods = false
) //表示是一个配置类,可以给容器中添加组件
@EnableConfigurationProperties({ServerProperties.class})// 启用ConfigurationProperties功能
@ConditionalOnWebApplication(
type = Type.SERVLET
)
@ConditionalOnClass({CharacterEncodingFilter.class})
@ConditionalOnProperty(
prefix = "server.servlet.encoding",
value = {"enabled"},
matchIfMissing = true
)
@EnableConfigurationProperties({ServerProperties.class})// 启用ConfigurationProperties功能
ServerProperties.class:
@ConfigurationProperties(
prefix = "server",
ignoreUnknownFields = true
)
@ConditionalOnWebApplication :spring底层@Conditional注解,根据不同的条件进行判断,如果满足条件整个配置类才会生效。
总结:
1.springboot会自动加载大量的自动配置类。
2.只要我们要用的组件有,我们就不需要再去配置
3.给容器添加组件的时候。会从properties类中获取某些属性。我们就可以在配置文件中指定这些属性。
xxxxxAutoConfiguration:自动配置类
给容器中添加属性:
xxxxProperties:封装配置文件中的相关属性。
springboot_自动配置原理的更多相关文章
- spring boot实战(第十三篇)自动配置原理分析
前言 spring Boot中引入了自动配置,让开发者利用起来更加的简便.快捷,本篇讲利用RabbitMQ的自动配置为例讲分析下Spring Boot中的自动配置原理. 在上一篇末尾讲述了Spring ...
- SpringBoot自动配置原理
前言 只有光头才能变强. 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y 回顾前面Spring的文章(以学习的顺序排好): S ...
- SpringBoot的自动配置原理过程解析
SpringBoot的最大好处就是实现了大部分的自动配置,使得开发者可以更多的关注于业务开发,避免繁琐的业务开发,但是SpringBoot如此好用的 自动注解过程着实让人忍不住的去了解一番,因为本文的 ...
- 3. SpringBoot ——自动配置原理浅析
SpringBoot的功能之所以强大,离不开它的自动配置这一大特色.但估计很多人只是知其然而不知其所以然.下面本人对自动配置原理做一个分析: 在使用SpringBoot时我们通过引入不同的Starte ...
- spring boot 自动配置原理
1).spring boot启动的时候加载主配置类,开启了自动配置功能@EnableAutoConfiguration,先看一下启动类的main方法 public ConfigurableApplic ...
- Spring Boot 自动配置原理(精髓)
一.自动配置原理(掌握) SpringBoot启动项目会加载主配置类@SpringBootApplication,开启@EnableAutoConfiguration自动配置功能 @EnableAut ...
- Spring Boot自动配置原理、实战
Spring Boot自动配置原理 Spring Boot的自动配置注解是@EnableAutoConfiguration, 从上面的@Import的类可以找到下面自动加载自动配置的映射. org.s ...
- 5. SprigBoot自动配置原理
配置文件到底能写什么?怎么写? 都可以在SpringBoot的官方文档中找到: 配置文件能配置的属性参照 1.自动配置原理: 1).SpringBoot启动的时候加载主配置类,开启了自动配置功 ...
- 3springboot:springboot配置文件(外部配置加载顺序、自动配置原理,@Conditional)
1.外部配置加载顺序 SpringBoot也可以从以下位置加载配置: 优先级从高到低 高优先级的配置覆盖低优先级的配置,所有的配置会形成互补配置 1.命令行参数 所有的配置都可以在命令行上进行指定 ...
随机推荐
- PIX防火墙配置A/S故障切换
PIX防火墙配置A/S故障切换 1.基本命令 failover show failover failover lan enable failover lan interface zwish e2 fa ...
- Rocket - devices - TLZero
https://mp.weixin.qq.com/s/JHjUZncEcoZpRxIS1ECV5g 简单介绍TLZero的实现. 1. /dev/null /dev/null最主要的特点是写入的数据被 ...
- linux 最基本的命令
1.说一些你比较常用linux指令 1.1.ls/ll.cd.mkdir.rm-rf.cp.mv.ps -ef | grep xxx.kill.free-m.tar -xvf file.tar.(说那 ...
- Java试题错题集01
1.javac与java命令 两个命令 javac 和 java. javac 后面跟着的是java文件的文件名,例如 HelloWorld.java. 该命令用于将 java 源文件编译为 clas ...
- Java实现洛谷 P1007独木桥
题目背景 战争已经进入到紧要时间.你是运输小队长,正在率领运输部队向前线运送物资.运输任务像做题一样的无聊.你希望找些刺激,于是命令你的士兵们到前方的一座独木桥上欣赏风景,而你留在桥下欣赏士兵们.士兵 ...
- Java实现 LeetCode 703 数据流中的第K大元素(先序队列)
703. 数据流中的第K大元素 设计一个找到数据流中第K大元素的类(class).注意是排序后的第K大元素,不是第K个不同的元素. 你的 KthLargest 类需要一个同时接收整数 k 和整数数组n ...
- Java实现 LeetCode 455 分发饼干
455. 分发饼干 假设你是一位很棒的家长,想要给你的孩子们一些小饼干.但是,每个孩子最多只能给一块饼干.对每个孩子 i ,都有一个胃口值 gi ,这是能让孩子们满足胃口的饼干的最小尺寸:并且每块饼干 ...
- Java实现 LeetCode 109 有序链表转换二叉搜索树
109. 有序链表转换二叉搜索树 给定一个单链表,其中的元素按升序排序,将其转换为高度平衡的二叉搜索树. 本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1. ...
- vs2019离线下载安装包
官方的离线安装说明-->点击打开 1.下载 vs2019引导程序 ,选择你所需的版本下载,我选择了企业版 vs_enterprise__184447765.1558180718.exe 2.设置 ...
- AWS—Xshell工具远程登录EC2虚拟机
一.创建AWS账户(已有AWS账号的请跳过) 访问 https://amazonaws-china.com/cn/,点击创建AWS账户,根据提示填写个人相关信息,创建AWS账户. 二.创建EC2虚拟机 ...