zoukankan      html  css  js  c++  java
  • SpringBoot自动配置原理

    前言

    只有光头才能变强。

    文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y

    回顾前面Spring的文章(以学习的顺序排好):

    作为一名Java程序员,就不可能不了解SpringBoot,如果不了解(赶紧学!)

    一、SpringBoot的自动配置原理

    不知道大家第一次搭SpringBoot环境的时候,有没有觉得非常简单。无须各种的配置文件,无须各种繁杂的pom坐标,一个main方法,就能run起来了。与其他框架整合也贼方便,使用EnableXXXXX注解就可以搞起来了!

    所以今天来讲讲SpringBoot是如何实现自动配置的~

    1.1三个重要的注解

    我们可以发现,在使用main()启动SpringBoot的时候,只有一个注解@SpringBootApplication

    只有一个@SpringBootApplication注解

    我们可以点击进去@SpringBootApplication注解中看看,可以发现有三个注解是比较重要的:

    SpringBootApplication注解详情

    • @SpringBootConfiguration:我们点进去以后可以发现底层是Configuration注解,说白了就是支持JavaConfig的方式来进行配置(使用Configuration配置类等同于XML文件)。
    • @EnableAutoConfiguration:开启自动配置功能(后文详解)
    • @ComponentScan:这个注解,学过Spring的同学应该对它不会陌生,就是扫描注解,默认是扫描当前类下的package。将@Controller/@Service/@Component/@Repository等注解加载到IOC容器中。

    所以,Java3yApplication类可以被我们当做是这样的:

    
    @SpringBootConfiguration
    @EnableAutoConfiguration
    @ComponentScan
    public class Java3yApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(Java3yApplication.class, args);
        }
    }
    

    1.2重点EnableAutoConfiguration

    我们知道SpringBoot可以帮我们减少很多的配置,也肯定听过“约定大于配置”这么一句话,那SpringBoot是怎么做的呢?其实靠的就是@EnableAutoConfiguration注解。

    简单来说,这个注解可以帮助我们自动载入应用程序所需要的所有默认配置

    介绍有一句说:

    if you have tomcat-embedded.jar on your classpath you are likely to want a TomcatServletWebServerFactory

    如果你的类路径下有tomcat-embedded.jar包,那么你很可能就需要TomcatServletWebServerFactory

    我们点进去看一下,发现有两个比较重要的注解:

    EnableAutoConfiguration注解详情

    • @AutoConfigurationPackage:自动配置包
    • @Import:给IOC容器导入组件

    1.2.1AutoConfigurationPackage

    网上将这个@AutoConfigurationPackage注解解释成自动配置包,我们也看看@AutoConfigurationPackage里边有什么:

    AutoConfigurationPackage注解实现

    我们可以发现,依靠的还是@Import注解,再点进去查看,我们发现重要的就是以下的代码:

    
    @Override
    public void registerBeanDefinitions(AnnotationMetadata metadata,
    		BeanDefinitionRegistry registry) {
    	register(registry, new PackageImport(metadata).getPackageName());
    }
    
    

    默认的情况下就是将:主配置类(@SpringBootApplication)的所在包及其子包里边的组件扫描到Spring容器中。

    • 看完这句话,会不会觉得,这不就是ComponentScan的功能吗?这俩不就重复了吗?

    我开始也有这个疑问,直到我看到文档的这句话:

    it will be used when scanning for code @Entity classes.
    It is generally recommended that you place EnableAutoConfiguration (if you're
    not using @SpringBootApplication) in a root package so that all sub-packages
    and classes can be searched.

    比如说,你用了Spring Data JPA,可能会在实体类上写@Entity注解。这个@Entity注解由@AutoConfigurationPackage扫描并加载,而我们平时开发用的@Controller/@Service/@Component/@Repository这些注解是由ComponentScan来扫描并加载的。

    • 简单理解:这二者扫描的对象是不一样的。

    1.2.2回到Import

    我们回到@Import(AutoConfigurationImportSelector.class)这句代码上,再点进去AutoConfigurationImportSelector.class看看具体的实现是什么:

    得到很多配置信息

    我们再进去看一下这些配置信息是从哪里来的(进去getCandidateConfigurations方法):

    通过SpringFactoriesLoader来加载

    这里包装了一层,我们看到的只是通过SpringFactoriesLoader来加载,还没看到关键信息,继续进去:

    跟踪实现

    简单梳理:

    • FACTORIES_RESOURCE_LOCATION的值是META-INF/spring.factories
    • Spring启动的时候会扫描所有jar路径下的META-INF/spring.factories,将其文件包装成Properties对象
    • 从Properties对象获取到key值为EnableAutoConfiguration的数据,然后添加到容器里边。

    从Properties对象获取到EnableAutoConfiguration.class对应的值,然后添加到容器里边

    最后我们会默认加载113个默认的配置类:

    有兴趣的同学可以去翻一下这些文件以及配置类哦:

    加载的配置类和文件的信息

    1.3总结

    @SpringBootApplication等同于下面三个注解:

    • @SpringBootConfiguration
    • @EnableAutoConfiguration
    • @ComponentScan

    其中@EnableAutoConfiguration是关键(启用自动配置),内部实际上就去加载META-INF/spring.factories文件的信息,然后筛选出以EnableAutoConfiguration为key的数据,加载到IOC容器中,实现自动配置功能!

    自动配置功能

    官网文档参考:

    英语不好的同学可以像我一样,对照着来看:

    一边插件,一边原文

    最后

    乐于输出干货的Java技术公众号:Java3y。公众号内有200多篇原创技术文章、海量视频资源、精美脑图,不妨来关注一下!

    帅的人都关注了

    觉得我的文章写得不错,不妨点一下

  • 相关阅读:
    css div position to parent
    linux 解压缩/压缩命令大全
    button with backgroundimage programmaticaly
    使用数组初始化vector 对象
    AudioServicesPlaySystemSound
    objective-c 中随机数的用法 (3种:arc4random() 、random()、CCRANDOM_0_1() )
    指针和多维数组(例子需要好好消化理解)
    很经典的赋值算法之一:动态为数组有序赋值
    string 类的c_str 的成员函数
    自由存储区的空间 C++和C
  • 原文地址:https://www.cnblogs.com/Java3y/p/10315285.html
Copyright © 2011-2022 走看看