震惊:Springboot的自动配置原理竟如此简单

177 阅读2分钟

前言

本文主要通过 @SpringBootApplication 启动类注解来分析一下 Springboot 的自动配置原理,话不多说直接上源码。

源码分析

@SpringBootApplication的源码如下:

@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) })
  1. 看第一个注解:@SpringBootConfiguration 的源码
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
    省略具体内容......
}

主要的注解就一个 @Configuration 代表当前是一个配置类

2.先看第三个注解

@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
      @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })

分析:

  • @ComponentScan:指定扫描注解内容
  • excludeFilters:指定扫描的时候按照什么规则排除那些组件(格式:excludeFilters = Filter[])
  • @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class):type = FilterType.CUSTOM 表示按照自定义方式排除组件,classes = TypeExcludeFilter.class) 具体的方式实现类

3.最后看第二个注解也是实现自动配置的关键 @EnableAutoConfiguration,先看源码

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
    省略具体内容......
}

源码中加入了两个注解:@AutoConfigurationPackage@Import(AutoConfigurationImportSelector.class)

a. 先看第一个注解 @AutoConfigurationPackage 的源码

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {

}

可以看到有 @Import 注解导入了 AutoConfigurationPackages.Registrar.class 这个类。再看一下这个类的内部类 Registrar 的实现

image.png

通过上面的截图可以看到 Registrar 的 registerBeanDefinitions 方法中注册了对应包扫描的路径。这也是为什么我们写在对应包下的注解能够被扫描生效的原因。

b. 再看第二个注解 @Import(AutoConfigurationImportSelector.class) 这个注解也是导入了 AutoConfigurationImportSelector.class 这个类。 这个类的具体调用链如下图

image.png 最终 classLoader.getResources(FACTORIES_RESOURCE_LOCATION) 获取了 FACTORIES_RESOURCE_LOCATION 这个资源文件

public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";

即在springboot启动的时候会去加载 "META-INF/spring.factories" 文件。

image.png 通过上图可以看见:springboot的jar中存在这个文件,其中定义了所有的启动时就要给容器中加载的所有配置类。这也是为什么springboot能够实现自动装配的原因,当然了这些配置也不是全是都是开启,有些需要我们主动的去开启。

总结

本文通过 @SpringBootApplication 的3个注解源码解析了自动装配的原理,希望大家通过这篇文章能对此有个大致的概念。

finally

public void isLike(){
    boolean 喜欢 = true;
    if(喜欢){
        "关注公众号:程序猿自来也 ";
        "扫他 ↓↓↓↓↓↓"
    }
}

cxyzilaiye.jpg