从源码分析 spring 如何实现 auto configuration
前言
spring-boot auto configuration 可以使得 spring 可以根据 classpath 有哪些 class, 有哪些 property 等来猜测用户需要哪些 bean, 并生成这些 bean 的实例。
实现
auto configuration 功能由两个功能实现:一个是 spring bean factory, 用于读取 spring.factories 文件加载 Configuration 类;另一个是相当于 @Import 注解将 spring bean factory 配置的类导入并解析其中的配置。
auto configuration 功能由 @EnableAutoConfiguration 注解打开
1 | ... |
由 @EnableAutoConfiguration 的定义可以看出 auto configuration 功能主要由 AutoConfigurationImportSelector 和 AutoConfigurationPackages.Registrar 两个类实现
AutoConfigurationImportSelector 是一个 DeferredImportSelector,DeferredImportSelector 是在所有 @Configuration 类处理后再进行处理的 ImportSelector。 AutoConfigurationImportSelector 的所有用户定义的 @Configuration 类处理之后,从 spring.factories 中加载 @Configuration 类。
1 | public class AutoConfigurationImportSelector implements DeferredImportSelector, |
示例
使用 auto configuration 对 redis 进行配置。 在使用 spring-boot 整合 redis 时,只需要通过 maven 引入 spring-boot-starter-data-redis 依赖,然后配置 spring.redis.host,spring.redis.port(单机)或spring.redis.cluster.nodes (集群) 就可以使用。 原理是 spring-boot 默认会引入 spring-boot-autoconfigure, 这个 jar 包含了大部分像用的 java 组件的 auto configuration 配置。 例如针对 redis, spring-boot-autoconfigure 在它的 spring.factories 文件中有如下定义
1 | org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ |
这样 spring 的 auto configuration 机制就会在启动过程中处理 RedisAutoConfiguration
1 |
|
使 RedisAutoConfiguration 生效的条件是 @ConditionalOnClass(RedisOperations.class), 表示当 classpath 中存在类 RedisOperations 时生效。@EnableConfigurationProperties(RedisProperties.class) 表示它会使用到 RedisProperties 类,spring 会注册一个 RedisProperties 实例到容器并给它注入相关的属性。
RedisAutoConfiguration 定义了 redisTemplate 和 stringRedisTemplate, 都需要 RedisConnectionFactory 作参数, 而 LettuceConnectionConfiguration 和 JedisConnectionConfiguration 就是用来定义 RedisConnectionFactory 的: 如果 classpath 中存在 RedisClient, 就使用 lettuce, 如果存在 GenericObjectPool 等就使用 jedis。在创建 RedisConnectionFactory 实例时,会根据配置的是 spring.redis.host 还是 spring.redis.cluster.nodes 来决定是使用单机模式还是集群模式.