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_自动配置原理的更多相关文章

  1. spring boot实战(第十三篇)自动配置原理分析

    前言 spring Boot中引入了自动配置,让开发者利用起来更加的简便.快捷,本篇讲利用RabbitMQ的自动配置为例讲分析下Spring Boot中的自动配置原理. 在上一篇末尾讲述了Spring ...

  2. SpringBoot自动配置原理

    前言 只有光头才能变强. 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y 回顾前面Spring的文章(以学习的顺序排好): S ...

  3. SpringBoot的自动配置原理过程解析

    SpringBoot的最大好处就是实现了大部分的自动配置,使得开发者可以更多的关注于业务开发,避免繁琐的业务开发,但是SpringBoot如此好用的 自动注解过程着实让人忍不住的去了解一番,因为本文的 ...

  4. 3. SpringBoot ——自动配置原理浅析

    SpringBoot的功能之所以强大,离不开它的自动配置这一大特色.但估计很多人只是知其然而不知其所以然.下面本人对自动配置原理做一个分析: 在使用SpringBoot时我们通过引入不同的Starte ...

  5. spring boot 自动配置原理

    1).spring boot启动的时候加载主配置类,开启了自动配置功能@EnableAutoConfiguration,先看一下启动类的main方法 public ConfigurableApplic ...

  6. Spring Boot 自动配置原理(精髓)

    一.自动配置原理(掌握) SpringBoot启动项目会加载主配置类@SpringBootApplication,开启@EnableAutoConfiguration自动配置功能 @EnableAut ...

  7. Spring Boot自动配置原理、实战

    Spring Boot自动配置原理 Spring Boot的自动配置注解是@EnableAutoConfiguration, 从上面的@Import的类可以找到下面自动加载自动配置的映射. org.s ...

  8. 5. SprigBoot自动配置原理

      配置文件到底能写什么?怎么写? 都可以在SpringBoot的官方文档中找到: 配置文件能配置的属性参照   1.自动配置原理: 1).SpringBoot启动的时候加载主配置类,开启了自动配置功 ...

  9. 3springboot:springboot配置文件(外部配置加载顺序、自动配置原理,@Conditional)

    1.外部配置加载顺序 SpringBoot也可以从以下位置加载配置: 优先级从高到低 高优先级的配置覆盖低优先级的配置,所有的配置会形成互补配置  1.命令行参数 所有的配置都可以在命令行上进行指定 ...

随机推荐

  1. bootstrap table Showing 1 to 5 of 5 rows 页码显示英文

    注意导包先后顺序bootstrap-table-zh-CN.js链接:https://cdn.bootcdn.net/ajax/libs/bootstrap-table/1.16.0/locale/b ...

  2. parrot os安装vmware pro

    转载https://www.linuxtechi.com/install-vmware-workstation-14-debian-9/ Open the terminal and execute t ...

  3. Jenkins漏洞利用复现

    一.未授权访问 访问url: http://172.16.20.134:8080/script 命令执行 println "ls -al".execute().text 也可以利用 ...

  4. 使用RTL进行硬件模型编程的局限性

    https://mp.weixin.qq.com/s/Nj_d3hwgNX4kWVtKsqMSWg   ​​   硬件模型编程,即Hardware Model Programming.在RTL抽象级别 ...

  5. WALT(Window Assisted Load Tracking)学习

    QCOM平台使用WALT(Window Assisted Load Tracking)作为CPU load tracking的方法:相对地,ARM使用的是PELT(Per-Entity Load Tr ...

  6. java实现第三届蓝桥杯方块填数

    方块填数 "数独"是当下炙手可热的智力游戏.一般认为它的起源是"拉丁方块",是大数学家欧拉于1783年发明的. 如图[1.jpg]所示:6x6的小格被分为6个部 ...

  7. 在WinForms里嵌入MediaPlayer的一些版本问题, tlbimp导入, 以及不导入而纯用C#+字符串来动态调用.

    网上很多写使用WindowsMediaPlayer WMP控件的文章. 大多数都是从工具栏或COM导入. 最近正在做的CEF整合Asp.Net Core Blazor server side的过程中, ...

  8. intput子系统

    1.按键驱动程序的第一个版本:day07/04      //内核模块的基本要求   init.h module.h LICENSE      struct cdev btn_cdev;      b ...

  9. sql server 取多条数据的最大值

    实列: SELECT a.BillDate '[开票时间]', a.Hdbh '[运单号]', a.Status '运单状态', a.DisplayStatus '运单状态字', b.name '开票 ...

  10. Spting:基于注解的组件化管理

    @Component,@Controller(控制层),@Service(业务层),@Repository(持久层) 以上四个注解的功能完全相同,不过在实际开发中,要在不同功能的类上加上响应的注解 1 ...