- 内容简介
- 前言
- 第 1 章 第一个 Spring Boot 项目
- 第 2 章 集成 MySQL 数据库
- 第 3 章 集成 Spring Data JPA
- 第 4 章 使用 Thymeleaf 模板引擎
- 第 5 章 Spring Boot 事务支持
- 第 6 章 使用过滤器和监听器
- 第 7 章 集成 Redis 缓存
- 第 8 章 集成 Log4j 日志
- 8.3 使用 Log4j 记录日志
- 第 9 章 Quartz 定时器和发送 Email
- 第 10 章 集成 MyBatis
- 第 11 章 异步消息与异步调用
- 第 12 章 全局异常处理与 Retry 重试
- 第 13 章 集成 MongoDB 数据库
- 第 14 章 集成 Spring Security
- 第 15 章 Spring Boot 应用监控
- 第 16 章 集成 Dubbo 和 Zookeeper
- 第 17 章 多环境配置与部署
- 第 18 章 Spring Boot 原理解析
- 参考文献
18.1 回顾入口类

18.1.1 MySpringBootApplication 入口类
首先,我们先来回顾一下项目 my-spring-boot 的入口类 MySpringBootApplication,具体代码如下:
在入口类 MySpringBootApplication 中,@SpringBootApplication 和 main 方法是 Spring Boot 自动生成的,其他注解都是我们在学习 Spring Boot 时整合其他技术添加上去的。接下来就和大家一起看看 @SpringBootApplication 和 SpringApplication.run 方法到底为我们做了些什么。
18.1.2 @SpringBootApplication 的原理
@SpringBootApplication 开启了 Spring 的组件扫描和 Spring Boot 自动配置功能。实际上它是一个复合注解,包含 3 个重要的注解:@SpringBootConfiguration、@ EnableAutoConfiguration、@ComponentScan,其源代码如下:
- @SpringBootConfiguration 注解:标明该类使用 Spring 基于 Java 的注解,Spring Boot 推荐我们使用基于 Java 而不是 XML 的配置,所以本书的实战例子都是基于 Java 而不是 XML 的配置。本书使用的 Spring Boot 版本为 2.0.0.RC1。查看 @SpringBootConfiguration 源代码,可以看到它对 @Configuration 进行了简单的“包装”,然后取名为 SpringBootConfiguration。@SpringBootConfiguration 源代码如下:
我们对 @Configuration 注解并不陌生,它就是 JavaConfig 形式的 Spring IoC 容器的配置类使用的 @Configuration。
- @EnableAutoConfiguration 注解:该注解可以开启自动配置的功能。@EnableAutoConfiguration 具体源代码如下:
从 @EnableAutoConfiguration 的源代码可以看出,其包含 @Import 注解。而我们知道,@Import 注解的主要作用就是借助 EnableAutoConfigurationImportSele ctor 将 Spring Boot 应用所有符合条件的 @Configuration 配置都加载到当前 Spring Boot 创建并使用的 Ioc 容器中,Ioc 容器就是我们所说的 Spring 应用程序上下文 ApplicationContext。学习过 Spring 框架就知道,Spring 框架提供了很多 @Enable 开头的注解定义,比如 @EnableScheduling、@EnableCaching 等。而这些 @Enable 开头的注解都有一个共同的功能,就是借助 @Import 的支持收集和注册特定场景相关的 bean 定义。
- @ComponentScan 注解:启动组件扫描,开发的组件或 bean 定义能被自动发现并注入 Spring 应用程序上下文。比如我们在控制层添加 @Controller 注解、在服务层添加 @Service 注解和 @Component 注解等,这些注解都可以被 @ ComponentScan 注解扫描到。
在 Spring Boot 早期的版本中,需要在入口类同时添加这三个注解,但从 Spring Boot 1.2.0 开始,只要在入口类添加 @SpringBootApplication 注解即可。
18.1.3 SpringApplication 的 run 方法
除了 @SpringBootApplication 注解外,我们发现了入口类的一个显眼的地方,那就是 SpringApplication.run 方法。在 run 方法中,首先创建一个 SpringApplication 对象实例,然后调用 SpringApplication 的 run 方法。SpringApplication.run 方法的源代码如下:
从源代码可以看出,Spring Boot 首先开启了一个 SpringApplicationRunListeners 监听器,然后通过 createApplicationContext、prepareContext 和 refreshContext 方法创建、准备、刷新应用上下文 ConfigurableApplicationContext,通过上下文加载应用所需的类和各种环境配置等,最后启动一个应用实例。
18.1.4 SpringApplicationRunListeners 监听器
SpringApplicationRunListener 接口规定了 SpringBoot 的生命周期,在各个生命周期广播相应的事件(ApplicationEvent),实际调用的是 ApplicationListener 类。SpringApplicationRunListener 的源代码如下:
ApplicationListener 是 Spring 框架对 Java 中实现的监听器模式的一种框架实现。具体源代码如下:
ApplicationListener 接口只有一个方法 onApplicationEvent,所以自己的类在实现该接口的时候要实现该方法。如果在上下文 ApplicationContext 中部署一个实现了 ApplicationListener 接口的监听器,每当 ApplicationEvent 事件发布到 ApplicationContext 时,该监听器就会得到通知。如果我们要为 Spring Boot 应用添加自定义的 ApplicationListener,那么可以通过 SpringApplication.addListeners() 或者 SpringApplication.setListeners() 方法添加一个或者多个自定义的 ApplicationListener。
18.1.5 ApplicationContextInitializer 接口
在 Spring Boot 准备上下文 prepareContext 时,会对 ConfigurableApplicationContext 实例做进一步的设置或者处理。prepareContext 的源代码如下:
在准备上下文 prepareContext 方法中,通过 applyInitializers 方法对 context 上下文进行设置和处理。applyInitializers 具体源代码如下:
在 applyInitializers 方法中,主要调用 ApplicationContextInitializer 类的 initialize 方法对应用上下文进行设置和处理。ApplicationContextInitializer 本质上是一个回调接口,用于在 ConfigurableApplicationContext 执行 refresh 操作之前对它进行一些初始化操作。一般情况下,我们基本不需要自定义一个 ApplicationContextInitializer,如果真需要自定义一个 ApplicationContextInitializer,那么可以通过 SpringApplication. addInitializers() 设置。
18.1.6 ApplicationRunner 与 CommandLineRunner
ApplicationRunner 与 CommandLineRunner 接口执行点是在容器启动成功后的最后一步回调,我们可以在回调方法 run 中执行相关逻辑。ApplicationRunner 具体源代码如下:
CommandLineRunner 具体源代码如下:
在 ApplicationRunner 或 CommandLineRunner 类中只有一个 run 方法,但是它们的入参不一样,分别是 ApplicationArguments 和可变 String 数组。
如果有多个 ApplicationRunner 或 CommandLineRunner 实现类,而我们需要按一定顺序执行它们,那么可以在实现类上加上 @Order(value=整数值)注解,SpringBoot 会按照 @Order 中的 value 值从小到大依次执行。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论