一、SpringBoot初体验

一个典型的SpringBoot应用长什么样子呢?如果我们使用http://start.spring.io/创建一个最简单的依赖Web模块的SpringBoot应用,一般情况下, 我们会得到一个SpringBoot应用的启动类,如下面代码所示:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;©SpringBootApplication
public class DemoApplication {public static void main(String[] args) {SpringApplication.run(DemoApplication.class, args);    }
}

所有的SpringBoot无论怎么定制,本质上与上面的启动类代码是一样的,而以上代码示例中,**Annotation定义(@SpringBootApplication)类定义 (SpringApplication.run)**最为耀眼,那么要揭开SpringBoot应用的奥秘,很明显的,我们只要先从这两位开始就可以了。

二、@SpringBootApplication背后的秘密

@SpringBootApplication是一个"三体”结构,实际上它是一个复合 Annotation:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(...)
public @interface SpringBootApplication{...
}

虽然定义使用了多个Annotation进行了原信息标注,但实际上重要的只有三个Annotation:

  • @Configuration(@SpringBootConfiguration点开查看发现里面还是应用了@Configuration)
  • @EnableAutoConfiguration
  • @ComponentScan

所以,如果我们使用如下的SpringBoot启动类,整个SpringBoot应用依然可以与之前的启动类功能对等:

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

但每次都写三个Annotation显然过于繁琐,所以写一个@SpringBoot-Application这样的一站式复合Annotation显然更方便些。

1、@Configuration 创世纪

很多SpringBoot的代码示例都喜欢在启动类上直接标注@Configuration或者@SpringBootApplication,对于初接触SpringBoot的开发者来说,其实这种做法不便于理解,如果我们将上面的SpringBoot启动类拆分为两个独立的Java类,整个形势就明朗了:

@Configuration
@EnableAutoConfiguration
@ComponentScan
public class DemoConfiguration {@Beanpublic Controller controller() {return new Controller();}
}
public class DemoApplication {public static void main(String[] args) {SpringApplication.run(DemoConfiguration.class, args);}
}

2、@EnableAutoConfiguration的功效

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";Class<?>[] exclude() default {};String[] excludeName() default {};
}

其中最关键的要属@Import(AutoConfigurationImportSelector.class),借助AutoConfigurationImportSelector@EnableAutoConfiguration可以帮助SpringBoot应用将所有符合条件的@Configuration配置都加载到当前SpringBoot创建并使用的IoC容器。

借助于Spring框架原有的一个工具类:SpringFactoriesLoader的支持,@EnableAutoConfiguration可以智能的自动配置功效才得以大功告成!

SpringFactoriesLoader 自动配置幕后英雄

Spring的SpringFactoriesLoader工厂的加载机制类似java提供的SPI机制一样,是Spring提供的一种加载方式。只需要在classpath路径下新建一个文件META-INF/spring.factories,并在里面按照Properties格式填写好接口和实现类即可通过SpringFactoriesLoader来实例化相应的Bean。配置的格式为Key = Value形式,其中key可以是接口、注解、或者抽象类的全名。value为相应的实现类,当存在多个实现类时,用“,”进行分割。

对于 @EnableAutoConfiguration 来说,SpringFactoriesLoader 的用途稍 微不同 一些,其本意是为了提供SPI扩展的场景,而在@EnableAutoConfiguration的场景 中,它更多是提供了一种配置查找的功能支持,即根据@EnableAutoConfiguration 的完整类名 org.springframework.boot.autoconiigure.EnableAutoConfiguration 作为查找 的Key,获取对应的一组©Configuration类。

所以,@EnableAutoConfiguration自动配置的魔法其实就变成了:从 classpath 中搜寻所有 META-INF/spring.factories 配置文件,并将其中 org.spring・ framework.boot.autoconfigure.EnableAutoConfiguration 对应的配置项通过反射 (Java Reflection)实例化为对应的标注了 ©Configuration的JavaConfig形式的 IoC容器配置类,然后汇总为一个并加载到IoC容器。

3、@ComponentScan

@ComponentScan的功能其实就是自动扫描并加载符合条件的组件或bean定义,最终将这些bean定义加载到容器中。加载bean定义到Spring的IoC容器,当然我们也可以手工单个注册

参考:

  • 《SpringBoot揭秘+快速构建微服务体系》 第三章

@SpringBootApplication揭秘相关推荐

  1. spring揭秘_被问到了! Spring 和 Spring Boot 之间到底有啥区别?

    相信很多小伙伴和我一样,常用Spring 和Spring Boot 但是就是没有研究二者之间到底有什么区别? 今天就来大揭秘 ↓ 概述 对于 Spring和 SpringBoot到底有什么区别,我听到 ...

  2. 康复治疗学可以考计算机吗,【大揭秘】2018“人机对话”康复医学治疗技术专业技术资格考试...

    原标题:[大揭秘]2018"人机对话"康复医学治疗技术专业技术资格考试 昨天,关于"2018年康复医学治疗技术专业技术资格考试采用人机对话考试方式"的通知一经发 ...

  3. 零代价修复海量服务器的内核缺陷——UCloud内核热补丁技术揭秘

    下述为UCloud资深工程师邱模炯在InfoQ架构师峰会上的演讲--<UCloud云平台的内核实践>中非常受关注的内核热补丁技术的一部分.给大家揭开了UCloud云平台内核技术的神秘面纱. ...

  4. 红芯丑闻揭秘者 Touko 专访 | 关于红芯丑闻的更多内幕……

    专栏 | 九章算法 网址 | www.jiuzhang.com ❤ 红芯事件 近日,一则<自主研发的国产浏览器内核,红芯宣布获2.5亿C轮融资>的讯息再次将"国产自主创新&quo ...

  5. 揭秘vue——vue-cli3全面配置

    ★ vue-cli3 全面配置 ★ Nuxt.js 全面配置 创建项目 配置环境变量   通过在package.json里的scripts配置项中添加--mode xxx来选择不同环境   在项目根目 ...

  6. 【云周刊】第146期:史上最大规模人机协同的双11,12位技术大V揭秘背后黑科技...

    摘要: 史上最大规模人机协同的双11,12位技术大V揭秘背后黑科技,INTERSPEECH 2017系列 | 语音识别之语言模型技术,机器学习初学者必须知道的十大算法,云数据库SQL Server 2 ...

  7. 男人约会动机大揭秘。

    被人约是好事,但也要眼明心亮,男人约会动机大揭秘. 男人约会动机大揭秘: 1:这是一个有诚意的开始,表明他是早有计划和你约会的.至少,也说明他有相当的社交礼貌. 2:这个男人可能只是一时寂寞了,如果你 ...

  8. 3dmax图像采样器抗锯齿_内幕揭秘!同样的场景同一张图,用3DMAX网渲平台进行二次渲染时间竟然相差3个小时之多!...

    一个分辨率:4000*2000的室内客餐厅,3dmax版本是2014版本,渲染器版本为vray3.63,机器:阿里云1台服务器,这个同样的场景同样的参数同一张图,用3dmax网渲平台进行二次渲染发现时 ...

  9. EIGRP OSFP 利用NULL0接口防止路由环路 Loopback Null0接口揭秘

    在EIGRP中,只要发生总结就会在路由表中自动产生一条指向NULL0的路由条目,这条路由的直接意思是:匹配这条路由的数据包会被路由器丢掉.它的目的是为了避免在某些情况下产生路由环路. 以第三四学期的中 ...

最新文章

  1. matplotlib安装
  2. 花木兰到底好看不,我用Python爬取了几万条评论!
  3. 十大经典排序算法(上)
  4. 吴恩达深度学习1.4笔记_Neural Networks and Deep Learning_深层神经网络
  5. cognos安装过程各种问题跟解决方法
  6. mysql _bin编码_mysql中utf8_bin、utf8_general_ci、utf8_general_cs编码区别
  7. Python 标准库 —— os 模块
  8. android studio 找不到button对象_为什么那么多漂亮(真漂亮)并且条件优秀的女生找不到对象?...
  9. (error) CLUSTERDOWN Hash slot not served
  10. 小麦助教|教你培训机构如提高学员续费率!
  11. C++后台开发面试常考
  12. 2011计算机一级a,2011河北省大学生计算机一级A卷操作步骤
  13. CDN: trunk URL couldn‘t be downloaded的解决办法
  14. 男孩子学医好还是学计算机好,男孩子学医选什么专业好 最有前景的医学类专业...
  15. deepin使用印象笔记(Evernote)
  16. CSS中有哪几种方式能隐藏页面元素(8种)
  17. 抖音seo源码 短视频seo源码二次开发,怎么使用抖音seo源码,视频seo源码私有化部署?
  18. Runtime.getRuntime.exec的陷阱
  19. 客户端与服务器端的区别
  20. 工行华虹U盾在Vista和IE7下的解决方案

热门文章

  1. 斐波那契数列 青蛙跳台阶 变态跳台阶
  2. zookeeper 默认端口_ZooKeeper知识点汇总
  3. lua_path环境变量设置linux,ubuntu16.04安装lua环境
  4. java 注释 过时_Java 注解
  5. mysql修改客户端编码命令_mysql命令行修改字符编码
  6. python 二维数组长度_剑指offer二维数组中的查找【Java+Python】
  7. linux将日期和日历信息追加到文件中_Linux常用指令
  8. html文本域 高度自适应,textarea高度自适应,textarea随着内容高度变化
  9. bb10系统支持java吗_黑莓BB10怎么样 BlackBerry 10系统好用吗?
  10. mysql innodb文件_MySQL的InnoDB文件介绍