SpringBoot源码解析——自动配置原理

-目录

SpringBoot自动配置原理

  1、@SpringBootConfiguration

  2、@ComponentScan

  3、@EnableAutoConfiguration(关键)

     1)进入@AutoConfigurationPackage

      2)进入@Import(AutoConfigurationImportSelector.class)注解

  4、按需配置

  5、修改默认配置

  总结


SpringBoot自动配置原理

  主类上的注解@SpringBootApplication,ctrl+单击进入可知,相当于重点的几个注解组合

    ①.@SpringBootConfiguration

    ②.@EnableAutoConfiguration

    ③.@ComponentScan(.....)

@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) })
public @interface SpringBootApplication {

  1、@SpringBootConfiguration

    --> 就相当于是标志为这是一个配置类,等价于@Configuration

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {

  2、@ComponentScan

    --> 由该注解中的excludeFilters、@Filter等字眼看出就是指定扫描哪Spring注解的

  3、@EnableAutoConfiguration(关键)

     进入该注解可以看到有@AutoConfigurationPackage和@Import(AutoCo....)两个关键注解

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

     1)进入@AutoConfigurationPackage

        --> 有个关键注解:@Import(AutoConfigurationPackages.Registrar.class),给容器导入组件

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AutoConfigurationPackages.Registrar.class)   //给容器中导入一个组件
public @interface AutoConfigurationPackage {

          --> 查看Import导入的配置类Registrar到底注册什么,ctrl单机进入Registrar,大致就是利用Registrar给容器中导入一系列组件(由最后的toArray()可知,将指定的一个包下的所有组件导入进来)

      2)进入@Import(AutoConfigurationImportSelector.class)注解

        --> 看源码中 selectImports 方法,查看选择导入规则

@Override
	public String[] selectImports(AnnotationMetadata annotationMetadata) {
		if (!isEnabled(annotationMetadata)) {
			return NO_IMPORTS;
		}
		AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
		return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
	}

       --> 重点分析getAutoConfigurationEntry(annotationMetadata)方法给容器中批量导入一些组件

       --> 可以看出先拿到需要导入容器的配置类信息 configurations,然后就是对该配置类信息进行一些了筛选:removeDuplicates(去重)、chekExclude..(排除)、filter...等进行筛选过滤

       -->所以重点方法:List<String> configurations = getCandidateConfigurations(annotation...),该方法获取到所有需要导入到容器中的配置类

        -->可以看到,可获取到127个相关配置类(后面会解释这个127个来源:spring.factories)

        --> debug进入getCandidateConfigurations候选配置类方法,分析该方法是如何获取所需要导入容器中的配置类的

        -->①.查看loadFactoryNames方法,可以看出由spring的工厂加载器来加载一些东西的,所以再进入loadFactoryNames进行查看

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;
	}

        -->②.显然还要进而再进入loadFactoryNames方法中的loadSpringFactories查看

public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
        String factoryTypeName = factoryType.getName();
        return (List)loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
    }

         -->③.最终关键利用工厂加载 Map<String,List<String>> loadSpringFactories(@Nullable ClassLoader classLoader)得到所有的组件

         -->结论:默认扫描我们当前系统里面所有 META-INF/spring.factories 位置的文件

         -->spring-boot-autoconfigure-2.3.4.RELEASE.jar包里面也有META-INF/spring.factories

         -->文件里写死了spring-boot一启动就给容器中加载的所有配置类(auto Configure:127个

  4、按需配置

    虽然有127个场景的所有自动配置启动的时候默认全部加载。xxxAutoConfiguration

    但是都是由相关注解(@Conditional),安装条件装配规则,最终按需配置的,如图

  5、修改默认配置

    底层运用了@ConditionalOnBean、@ConditionalOnMissingBean、@Conditional等注解进行条件配置,即默认底层配好所有相应场景地组件的同时,还允许优先使用用户自己配置的

    下面看一下底层为我们配好的一些组件

    --> 关于springmvc的配置: 即不用像ssm整合那样些一堆配置信息于xml,web.xml中配置dispatcherservlet之类的了,如下图:

     -->文件解析器自动配置:联用了@ConditionalOnBean和@ConditionalOnMissingBean两个注解进行规范,即存在文件解析器MutipartResolver才生效(但是也要求用户没有定义相关名为multipartResolver的组件,避免发生冲突

     -->字符编码自动配置:也用到了注解@ConditionalOnMissingBean,只要用户有自己的配置,就以用户的优先

  总结

  • SpringBoot先加载所有的自动配置类 xxxAutoConfiguration
  • 每个自动配置类按照条件进行生效,默认都会绑定配置文件指定的值(条件以@Conditional等注解进行限定,配置以xxxProperties里面拿,而xxxProperties和配置文件进行了绑定)
  • 生效的配置类会给容器中装配很多组件(@Bean)
  • 只要容器中有这些组件,相当于这些功能就有了
  • 定制化配置

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

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

      如:xxxAutoConfiguration --> 导入许多组件 --> 组件从xxxProperties里面拿值 -->properties跟 application.properties进行了绑定

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值