[TOC]
> 来自艾编程coding老师讲义,很散,很碎,有一定 SpringBoot 基础看会比较好。
## 1.SpringBoot 启动过程
> 还可以参考:[Tomcat在SpringBoot中是如何启动的](https://my.oschina.net/luozhou/blog/3088908)
启动类示例:
```java
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
//程序的主入口
@SpringBootApplication //Springboot应用
public class DemoApplication {
public static void main(String[] args) {
//开启了一个服务!
SpringApplication.run(DemoApplication.class, args);
}
}
```
> applicationContext.xml < == > @Configuration
bean < == > @Bean
import < == > @Import
### 1.1 启动流程图

### 1.2 自动装配过程核心调用链
```java
@SpringBootApplication
--> @EnableAutoConfiguration
--> @AutoConfigurationImportSelector --> #selectImports --> #getAutoConfigurationEntry --> #getCandidateConfigurations
--> SpringFactoriesLoader --> #loadFactoryNames --> #loadSpringFactories --> #FACTORIES_RESOURCE_LOCATION (META-INF/spring.factories)
--> @AutoConfigurationPackage --> AutoConfigurationPackages.Registrar
```
其中``AutoConfigurationImportSelector#getCandidateConfigurations``方法很关键,会去读取``META-INF/spring.factories``。
源码如下:
```java
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;
}
```
### 1.3 ``SpringApplication.run()``大致流程
- 1.推断我们的应用是web应用还是 普通应用!
- 2.加载初始化!
- 3.设置监听器
- 4.推断main方法,找到运行的主类
核心部分源码如下:
```java
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
this.webApplicationType = WebApplicationType.deduceFromClasspath();
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}
```
### 1.4 YAML 配置文件
``Yet Another Markup Language``强调这种语言以数据做为中心,而不是以标记语言为重点。
> 语法要点:冒号后空一格、下一层级可用两个空格作为缩进表示、同级别配置左侧需要对齐。。
简单示例:
字面量键值对:
```yaml
k: value
```
对象,map
```yaml
# 这句是注释
student:
name: coding
age: 3
student: {name: coding, age: 3}
```
数组(List,Set)
```yaml
#语法
pets:
- cat
- dog
- pig
pets: [cat,dog,pig]
```
### 1.5 ``@ConfigurationProperties``
``@ConfigurationProperties``和 YAML 配置是黄金搭档。
> SpringBoot自动配置底层基本全部都使用了这个注解。
``@ConfigurationProperties`` VS ``@Value``
| 特性对比 | @ConfigurationProperties | @Value |
| -------------- | ------------------------ | ---------- |
| 功能 | 批量从配置文件中注入属性 | 一个个指定 |
| 松散绑定 | 支持 | 不支持 |
| SpEL | 不支持 | 支持 |
| JSR303数据校验 | 支持 | 不支持 |
| 复杂类型封装 | 支持 | 不支持! |
| | | |
在配置类中,通过注解``@EnableConfigurationProperties``即可自动装配``@ConfigurationProperties``注解标记的配置类。
> 可参考:[DemoServiceProperties.java](https://gitee.com/sherlocky/springboot2-learning/blob/master/demo-spring-boot-autoconfigure/src/main/java/com/sherlocky/springboot2/starter/demo/DemoServiceProperties.java)、[DemoServiceAutoConfiguration.java](https://gitee.com/sherlocky/springboot2-learning/blob/master/demo-spring-boot-autoconfigure/src/main/java/com/sherlocky/springboot2/starter/demo/DemoServiceAutoConfiguration.java)
## 2.十五次架构演进
### 2.1 单体架构

问题:用户量增大。
### 2.2 tomcat 和数据库分离

问题:用户暴增,并发读写,瓶颈!
### 2.3 引入分布式缓存本地缓存

问题:缓存一致性问题,缓存穿透、缓存雪崩.... 热点数据集中失效等。
### 2.4 负载均衡

问题:单点登陆,session共享,文件上传下载!
### 2.5 数据库读写分离

问题: 数据库同步,数据一致性问题!
### 2.6 数据库按照业务分库

### 2.7 把大表拆分为一个个小表

问题:大规模并发!
### 2.8 LVS,F5,多个nginx实现负载均衡

### 2.9 通过DNS 实现机房的负载均衡

机房级的水平扩展
### 2.10 引用NoSQL数据库,搜索引擎

### 2.11 大应用拆分为小应用

### 2.12 将公共模板抽象为微服务化

### 2.13 引入服务总线

### 2.14容器化

Docker + k8s。
### 2.15 云平台系统

Iaas: 基础设施即服务
Paas:平台即服务
Sass: 软件即服务
[艾编程]SpringBoot启动过程浅析&服务架构演进