SpringBoot自动配置原理

前言

SpringBoot帮我们把一切都做好了,让我们只关注业务逻辑的开发,让我们对原理一探究竟。

@SpringBootApplication注解

Spring的一切自动配置起源于主程序的SpringBootApplication注解,进入SpringBootApplication注解可以看到, 他是由三个注解组合而成的。

  • @SpringBootConfiguration
  • @EnableAutoConfiguration
  • @ComponentScan

@SpringBootConfiguration

 用@Configuration注解标注, 就表示SpringBootConfiguration是一个配置类(Springboot的核心配置类),就说明了我们创建的Springboot应用的主程序类也是一个配置类,

@ComponentScan

指定包的扫描,腰扫描那些包。

@EnableAutoConfiguration (核心重点)

由两个个注解组合而成       

@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})

@AutoConfigurationPackage  

进入@AutoConfigurationPackage 可以看到这个类上面标注了一个@Import({Registrar.class})  注解, 表示给容器导入一个组件  

@Import({Registrar.class})
public @interface AutoConfigurationPackage {
    String[] basePackages() default {};

    Class<?>[] basePackageClasses() default {};
}

我们进入@Import({Registrar.class})的Registrar.class类看一下,到底要导入什么组件。

  • 利用Registrar给容器中导入一系列组件
  • 将指定的一个包下的所有组件导入进来?MainApplication 所在包下。

Registrar类中有两个方法, 第一个方法就是批量注册组建的,这里的参数metadata就是标注该注解的类,最终也就是我们创建的SpringBoot应用程序的主程序启动类。


AutoConfigurationPackages.register方法中参数
(new AutoConfigurationPackages.PackageImports(metadata)).getPackageNames().toArray(new String[0]) 利用标注在主程序的类的元数据计算机出主程序所在的包名,创建一个数组然后注册到容器,这也就说明了为什么我们创建的Controller等要在主类包的下面。(register就是把某一个包下的所有组件批量注册进去)

 @Import({AutoConfigurationImportSelector.class})

给容器中批量导入组件,导入那些组件呢?

进入AutoConfigurationImportSelector.class, 有一个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());
        }
    }

selectImports方法中有一个getAutoConfigurationEntry方法, 所有的东西都是通过这个方法得到的,然后再autoConfigurationEntry.getConfigurations()得到配置返回。

我们看一下getAutoConfigurationEntry源码,List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes); 活得了134个类,这是全部要导入到容器里面的。

 我们再继续往下看,看看List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes) 是如何获取这134个组建的呢?一直从方法里面往下调,一直到SpringFactoriesLoader的loadSpringFactories方法。

从META-INF/spring.factories位置来加载一个文件。 默认扫描我们当前系统里面所有META-INF/spring.factories位置的文件 spring-boot-autoconfigure-2.3.4.RELEASE.jar(这是核心自动配置类)包里面也有META-INF/spring.factories

文件里面写死了spring-boot一启动就要给容器中加载的所有配置类

 自动配置:

只有我们在pom.xml文件中引入了的组件才会生效, 因为每个XXXautoConfigure是通过@  注解进行条件装配的,如果我们在pom.xml文件中引入了相关依赖,那么这个依赖jar就会生效,通过@ConditionalOnBean({CacheAspectSupport.class})条件的判断来决定是否注入Bean,下图,如果容器中没有CacheManager,那么整个类里面的方法就不执行了,如果存在那么就注入。

 Web自动配置

  • DispatcherServletRegistrationConfiguration

全流程原理:主类上的@SpringBootApplication注解上的@EnableAutoConfiguration注解。

通过@EnableAutoConfiguration上的@Import({AutoConfigurationImportSelector.class})

AutoConfigurationImportSelector中的selectImports方法一直往里调用,从META-INF/spring.factories位置来加载一个文件。 默认扫描我们当前系统里面所有META-INF/spring.factories位置的文件 spring-boot-autoconfigure-2.3.4.RELEASE.jar(这是核心自动配置类)包里面也有META-INF/spring.factories, 加载134个组件。再通过pom.xml文件中的导入的依赖场景按需加载。(其他如字符解析器,视图解析器都是这样注入的)

因为默认导入了spring-boot-starter-web场景, 那么web/servlet的依赖都会被导入DispatcherServletRegistrationConfiguration就是SpringMVC的前端控制器的自动配置。

WebMvcProperties的属性通过配置文件设置给dispatcherServlet实例

@EnableConfigurationProperties({WebMvcProperties.class})这个注解主要用来把配置文件的值绑定到WebMvcProperties这个类上并注入到容器

SpringBoot默认会在底层配好所有的组件。但是如果用户自己配置了以用户的优先

  • 底层配置的原理就是通过@ConditionalOnBean({XXX.class})条件的判断来决定是否注入Bean,注入的,如果我们要自定义配置,可以按照这种方式
 @Bean
    @ConditionalOnMissingBean({MultipartConfigElement.class, CommonsMultipartResolver.class})
    public MultipartConfigElement multipartConfigElement() {
        return this.multipartProperties.createMultipartConfig();
    }
@Bean
  @ConditionalOnMissingBean
  public CharacterEncodingFilter characterEncodingFilter() {
    }

总结:

  • SpringBoot先加载所有的自动配置类 xxxxxAutoConfiguration
  • 每个自动配置类按照条件进行生效,默认都会绑定配置文件指定的值。xxxxProperties里面拿。xxxProperties和配置文件进行了绑定
  • 生效的配置类就会给容器中装配很多组件
  • 只要容器中有这些组件,相当于这些功能就有了
  • 定制化配置

           用户直接自己@Bean替换底层的组件

           用户去看这个组件是获取的配置文件什么值就去修改。

xxxxxAutoConfiguration ---> 组件 ---> xxxxProperties里面拿值 ----> application.properties

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值