1 SpringBoot介绍

SpringBoot是在架构演进过程中,优化Spring开发流程而出现的,是对Spring开发进行了再次简化。

SpringBoot相比Spring做了哪些优化?

  1. 简化了Bean对象注入IoC容器的流程   
  2. 对配置文件进行了统一管理
  3. 容器内置化

main -> run -> refreshContext -> invokeBeanFactoryPostProcessor -> 扫描带有@Import注解的类 -> 调用selectImports方法

2 SpringBoot自动装配

2.1 SpringBoot集成Redis Demo

比如SpringBoot集成redis,只需要以下三步就可以通过RedisTemplate使用redis,不需要自己将RedisTemplate注入到IoC容器,这就是自动装配

(1) 导包

<dependency>
	<groupId>org.mybatis.spring.boot</groupId>
	<artifactId>mybatis-spring-boot-starter</artifactId>
	<version>1.1.1</version>
</dependency>

(2) redis相关配置

# master的名字是sentinel.conf配置文件里面的名称
# sentinel monitor redis-master 192.168.8.203 6379 2
spring.redis.sentinel.master=redis-master
spring.redis.sentinel.nodes=192.168.8.203:26379,192.168.8.204:26379,192.168.8.205:26379

# 连接池最大连接数(使用负值表示没有限制) 默认 8
spring.redis.lettuce.pool.max-active=8
# 连接池最大阻塞等待时间(使用负值表示没有限制) 默认 -1
spring.redis.lettuce.pool.max-wait=-1s
# 连接池中的最大空闲连接 默认 8
spring.redis.lettuce.pool.max-idle=8
# 连接池中的最小空闲连接 默认 0
spring.redis.lettuce.pool.min-idle=0

(3) 通过@Autowired注入RedisTemplate

2.2 自动装配过程

SpringBoot项目启动 –> 扫描@SpringBootApplication –> 里面带了@Configuration注解,表示该注解修饰的类是配置类 –> @EnableAutoConfiguuration注解里有@Import注解 –> @Import注解实际上导入了所有需要自动装配的配置类 –> @Import注解里有AutoConfigurationImportSelector类 –> AutoConfigurationImportSelector间接实现了ImportSelector接口

@EnableAutoConfiguuration

@Import(AutoConfigurationImportSelector.class) -> 会导入所有需要自动装配的配置类

AutoConfigurationImportSelector.class -> 返回配置类的类名

如何找到所有配置类? 通过SPI机制找到需要自动装配的配置类

RedisAutoConfiguration类就是自动注入RedisTemplate的配置类

3 SPI(Service Provider Interface)

甲方调用乙方接口,甲方制定好接口,然后自己调用自己制定的接口,由乙方实现接口;

(1) 甲方提供接口

(2) 乙方依赖甲方接口所在的包,并且创建接口实现类

(3) 在乙方实现类所在jar包中告诉甲方,实现类在哪,具体是什么实现类

(4) 甲方依赖乙方的jar包之后再进行调用,最终调用乙方实现类方法

JDK SPI通过ServiceLoader<SPIService> load = ServiceLoader.load(SPIService.class);

Spring SPI通过SpringFactoriesLoader.loadSpringFactories

Dubbo SPI通过ExtensionLoader.load

3.1 Jdk SPI

在resources/META-INF/services下创建以配置类全路径为名的文件,文件内部列举其所有实现类,多个实现类换行分开

(1) 根据Prefix + 接口全路径找到文件

(2) 解析文件,获取文件中配置的实现类

(3) 循环遍历反射获取配置类并实例化

3.2 Spring SPI

在每个组件项目路径resources/META-INF/spring.factories中配置了配置类,通过key-value方式配置接口与实现类

3.3 Dubbo SPI

以负载均衡算法为例,在resources/META-INF/dubbo或者在classpath/META-INF/services路径下创建org.apache.dubbo.rpc.cluster.LoadBalance文件,文件内部列举自定义实现类

// key-value形式, key是别名, value是自定义负载均衡算法类全路径
myloadbalance=com.example.dubbo.loadbalance.MyLoadBalance
random=com.example.dubbo.loadbalance.RandomLoadBalance
public class MyLoadBalance implements LoadBalance {
    @override
    public void select() {
        // TODO 负载均衡算法实现
    }
}
@Controller
public class UserController {
    // 使用自定义负载均衡算法
    @DubboReference(loadBalance="myloadbalance")
    IUserService userService;
}

(1) 加载文件,获取文件中配置的实现类

(2) 将所有实现类类名放到四个容器里面,不实例化

(3) 类调用的时候再实例化

4 SpringBoot启动源码分析

(1) 从main方法启动

(2) 判断当前项目运行环境类型,其实就是去所依赖的jar中寻找是否存在DispatcherHandler / DispatcherServlet

(3) 设置初始化器和监听器,用于对外扩展

(4) 创建环境变量environment,同时创建PropertySources容器,默认创建四个系统级别PropertySources

(5) 然后基于监听器机制,将本地配置文件,远程服务器的配置文件加入到PropertySources,进而加到Environment中

        a. 确定文件所在目录,从5个路径下寻找(classpath/*, classpath/config/*, /*, /config/*, /config/*/*)

        b. 确定文件名称(application.properties, application.yml)

        c. 如果是本地配置文件则通过IO流去读,如果是远程配置文件则通过HTTP去读

        d. 解析封装配置文件为PropertySource,并通过addLast追加到PropertySources

5 Starter组件

stater组件干了啥?

  1. 引springboot包
  2. 写RedisTemplate类
  3. 写配置类RedisAutoConfiguration,实现EnableAutoConfiguration接口
  4. 写spring.factories文件
  5. 打成jar包

xxx-spring-boot-starter与spring-boot-starter-xxx的区别?

  1. 前者是spring自身维护的starter,后者是第三方组件维护的starter
  2. spring自身维护的starter,目录下没有spring.factories文件,全都配置在spring-boot-autoconfigure项目中,但是不会全部注入到容器中,根据@ConditionalOnClass条件注入注解决定哪些配置类需要被注入到IoC容器中,而第三方组件维护的starter下都有spring.factories文件

版权声明:本文为luciferlongxu原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/luciferlongxu/article/details/127044616