SpringBoot 中 @SpringBootApplication 注解背后的三体结构探秘 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
hansonwang99
V2EX    程序员

SpringBoot 中 @SpringBootApplication 注解背后的三体结构探秘

  •  1
     
  •   hansonwang99
    hansonwang99 2018 年 7 月 30 日 3243 次点击
    这是一个创建于 2815 天前的主题,其中的信息可能已经有所发展或是发生改变。

    Profile


    概 述

    SpringBoot 约定大于配置 的功力让我们如沐春风,在我之前写的文章《从 SpringBoot 到 SpringMVC 》 也对比过 SpringBoot 和 SpringMVC 这两个框架,不过最终 SpringBoot 以超高的代码信噪比 和 易上手性 让我们映像颇深。

    但归根结底,不论 SpringBoot 或者 SpringMVC 应用本质上依然是一个基于 Spring 的应用,只不过在后者脸庞上蒙上了一层神秘的面纱而已!

    回到 SpringBoot 的话题,我们在开发基于 SpringBoot 的应用时,用到了一些新的注解和类,正式由于其存在,才让 JavaEE 的开发如鱼得水。这其中我们用的最多的注解之一,当属 SpringBoot 应用启动类上的 @SpringBootApplication 注解了

    本文就来看看它到底是个啥!



    @SpringBootApplication 背后到底是什么?

    @SpringBootApplication 注解实际上是 SpringBoot 提供的一个复合注解,我们来看一看其源码:

    @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 { ... } 

    看得很清楚,其是一个合成体,但其中最重要的三个注解分别是:

    • @SpringBootConfiguration

    • @EnableAutoConfiguration

    • @ComponentScan

    我们不妨称其为 “ 三体结构 ” 吧!

    如果我们不怕麻烦,在 SpringBoot 应用的启动类上用这个三个注解代替 @SpringBootApplication 注解发现也是没问题的:

    @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan public class TestSpringBootApplication { ... } 

    下面分别剖析一下这三个注解的功效!



    @SpringBootConfiguration

    看代码吧,代码里是这样写的:

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

    这说明 @SpringBootConfiguration 也是来源于 @Configuration,二者功能都是将当前类标注为配置类,并将当前类里以 @Bean 注解标记的方法的实例注入到 srping 容器中,实例名即为方法名。

    至于 @Configuration,我想在非 SpringBoot 时代大家应该不陌生吧,作用是配置 Spring 容器,也即 JavaConfig 形式的 Spring IoC 容器的配置类所使用。

    到目前来看,好像还没有什么新东西!!!



    @EnableAutoConfiguration

    再继续看代码,代码是这样的:

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

    @EnableAutoConfiguration 注解启用自动配置,其可以帮助 SpringBoot 应用将所有符合条件的 @Configuration 配置都加载到当前 IoC 容器之中,可以简要用图形示意如下:

    @EnableAutoConfiguration 幕后的组件调用关系

    接下来我们对照源码,来解释一下这个流程:

    • @EnableAutoConfiguration 借助 AutoConfigurationImportSelector 的帮助,而后者通过实现 selectImports() 方法来导出 Configuration

    selectImports()

    • AutoConfigurationImportSelector 类的 selectImports() 方法里面通过调用 Spring Core 包里 SpringFactoriesLoader 类的 **loadFactoryNames()**方法

    SpringFactoriesLoader.loadFactoryNames()

    • 最终通过 SpringFactoriesLoader.loadFactoryNames() 读取了 ClassPath 下面的 META-INF/spring.factories 文件来获取所有导出类。

    而 spring.factories 文件里关于 EnableAutoConfiguration 的配置其实就是一个键值对结构,样子大概长下面这样:

    spring.factories

    说了这么多,如果从稍微宏观一点的角度 概括总结 上述这一过程那就是:

    从 ClassPath 下扫描所有的 META-INF/spring.factories 配置文件,并将 spring.factories 文件中的 EnableAutoConfiguration 对应的配置项通过反射机制实例化为对应标注了 @Configuration 的形式的 IoC 容器配置类,然后注入 IoC 容器。



    @ComponentScan

    @ComponentScan 对应于 XML 配置形式中的 context:component-scan,用于将一些标注了特定注解的 bean 定义批量采集注册到 Spring 的 IoC 容器之中,这些特定的注解大致包括:

    • @Controller
    • @Entity
    • @Component
    • @Service
    • @Repository

    等等

    对于该注解,还可以通过 basePackages 属性来更细粒度的控制该注解的自动扫描范围,比如:

    @ComponentScan(basePackages = {"cn.codesheep.controller","cn.codesheep.entity"}) 

    可见 这个注解也并不是什么新东西!



    后 记

    由于能力有限,若有错误或者不当之处,还请大家批评指正,一起学习交流!

    作者更多的 SpringBt 实践文章在此:


    如果有兴趣,也可以抽点时间看看作者一些关于容器化、微服务化方面的文章:



    4 条回复    2018-07-31 00:31:26 +08:00
    hansonwang99
        1
    hansonwang99  
    OP
       2018 年 7 月 30 日 via iPhone
    又没人喷吗
    mmnsghgn
        2
    mmnsghgn  
       2018 年 7 月 31 日
    比较喜欢题图,可以告知一下来源吗?
    lhx2008
        3
    lhx2008  
       2018 年 7 月 31 日 via Android   1
    除了中间一段源码,其他都是官方手册的内容。还是支持吧。
    Lonely
        4
    Lonely  
       2018 年 7 月 31 日
    @zhengjian JetBrains 官网的
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1129 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 28ms UTC 23:12 PVG 07:12 LAX 16:12 JFK 19:12
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86