参考网页
SpringBoot集成Redis的原理
application.yml配置文件中的属性是如何读入到程序中的?
RedisProperties类(org.springframework.boot.autoconfigure.data.redis.RedisProperties)
application.properties配置参数示例
spring.redis.database=0
spring.redis.host=192.168.188.7
spring.redis.password=123
spring.redis.port=6379
spring.redis.pool.max-idle=8
spring.redis.pool.min-idle=0
spring.redis.pool.max-active=8
spring.redis.pool.max-wait=-1
application.yml配置参数示例
spring:
cache:
#缓存名称
#cache-names: guavaDemo
#缓存最大数量500条, 缓存失效时间 6个小时
#guava.spec: maximumSize=500,expireAfterWrite=360m
# REDIS (RedisProperties)
redis :
host : localhost # server host
port : 6379 # connection port
password : 123
database : 1
pool.max-idle : 8 # pool settings ...
pool.min-idle : 1
pool.max-active : 8
pool.max-wait : -1
源码
@ConfigurationProperties(prefix = "spring.redis")
public class RedisProperties {
/**
* Database index used by the connection factory.
*/
private int database = 0;
/**
* Redis url, which will overrule host, port and password if set.
*/
private String url;
/**
* Redis server host.
*/
private String host = "localhost";
/**
* Login password of the redis server.
*/
private String password;
/**
* Redis server port.
*/
private int port = 6379;
// 其它参数略
}
源码分析
此类被@ConfigurationProperties注解,表示从外部文件(如application.properties)注入属性值。application.properties中的参数会被自动封装到RedisProperties中。
调试--在RedisProperties中打个断点,比如设置database属性值的地方
把database 的属性值设置为1(默认为0,就是Redis数据库的第一个索引的库,1表示第二个索引的库)。在RedisProperties的setDatabase方法上打个断点,如下图
启动系统,运行到断点了,如下图
说明系统初始化时,确实运行到了RedisProperties的代码里面,并且根据application.properties文件的配置参数对RedisProperties的属性进行了注入。
RedisAutoConfiguration类
关键部分源码
/**
* EnableAutoConfiguration Auto-configuration for Spring Data's Redis support.
*
*/
@Configuration
// 如果有以下三个类,则可以初始化此类
@ConditionalOnClass({ JedisConnection.class, RedisOperations.class, Jedis.class })
// @EnableConfigurationProperties:对RedisProperties执行自动绑定属性值
@EnableConfigurationProperties(RedisProperties.class)
public class RedisAutoConfiguration {
@Configuration
// 如果有以下一个类,则可以初始化此类
@ConditionalOnClass(GenericObjectPool.class)
protected static class RedisConnectionConfiguration {
// 初始化JedisConnectionFactory工厂类对象,参数来自RedisProperties
// 配置参数有:线程池,sentinel,cluster
@Bean
@ConditionalOnMissingBean(RedisConnectionFactory.class)
public JedisConnectionFactory redisConnectionFactory()
throws UnknownHostException {
return applyProperties(createJedisConnectionFactory());
}
// 配置类
@Configuration
protected static class RedisConfiguration {
// 初始化bean
@Bean
@ConditionalOnMissingBean(name = "redisTemplate")
public RedisTemplate<Object, Object> redisTemplate(
RedisConnectionFactory redisConnectionFactory)
throws UnknownHostException {
RedisTemplate<Object, Object> template = new RedisTemplate<Object, Object>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
// 初始化bean
@Bean
@ConditionalOnMissingBean(StringRedisTemplate.class)
public StringRedisTemplate stringRedisTemplate(
RedisConnectionFactory redisConnectionFactory)
throws UnknownHostException {
StringRedisTemplate template = new StringRedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
}
源码分析
此类被@EnableConfigurationProperties注解,所以SpringBoot会触发对RedisProperties执行自动绑定属性值。
此类会自动创建bean对象: redis连接池JedisConnectionFactory和redis模板类(RedisTemplate和StringRedisTemplate)。直接在应用中通过@Autowire就可以注入以上对象。
比如使用RedisTemplate如下
项目启动类启动时如何关联到配置类RedisAutoConfiguration
启动类
查看源码@SpringBootApplication被@EnableAutoConfiguration注解
被@EnableAutoConfiguration注解时,SpringBoot启动时会扫描对应jar包中的META-INF/spring-autoconfigure-metadata.properties文件,并初始化里面的配置的类。查看spring-autoconfigure-metadata.properties,里面配置了上文的RedisAutoConfiguration类,所以我们可以直接在类中注入RedisTemplate
查看我的实际项目中@EnableAutoConfiguration的扫描对象
项目启动时,主启动类被@EnableAutoConfiguration注解,会扫描其引入的jar包中的spring.factories文件。
打开spring.factories文件,可以发现里面有org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration这个类。所以会初始化此类进行相关的配置。
★小结:application.yml配置文件中的属性是如何读入到程序中的?
1)项目主启动类上被@SpringBootApplication注解,@SpringBootApplication又被@EnableAutoConfiguration注解。@EnableAutoConfiguration会触发扫描项目引入的jar包中的spring.factories文件。主启动类再加上注解@EnableCaching后,这样就会触发初始化类org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration。
2)RedisAutoConfiguration被@EnableConfigurationProperties注解,会触发对RedisProperties执行自动绑定属性值。
3)RedisProperties类被@ConfigurationProperties注解,表示从外部文件(如application.properties)注入属性值。application.properties中的参数会被自动封装到RedisProperties中。
RedisCacheManager是如何被初始化的
总的思路
实际上SpringBoot中所有Bean都有默认的配置和实现,也就是什么都不写就可以直接运行。
但是如果程序员写一个Bean的实现,那么SpringBoot会采用程序员写的。
@EnableCaching和application.yml
缓存管理接口org.springframework.cache.CacheManager,SpringBoot就是通过此类实现缓存的管理。redis对应此接口的实现类是org.springframework.data.redis.cache.RedisCacheManager。下面介绍此类如何生成。
配置application.properties的spring.redis.* 属性后,主启动类加上注解@EnableCaching后,spring会执行RedisAutoConfiguration,初始化RedisTemplate和StringRedisTemplate。
猜测——虽然SpringBoot因为主启动类的@EnableAutoConfiguration注解会扫描引入的jar包的spring.factories文件,但是只有主启动类加上@EnableCaching注解后,诸如RedisAutoConfiguration的缓存类配置对象才会真的被初始化。
★SpringBoot如何对RedisCacheManager做的初始化--RedisCacheConfiguration会将RedisAutoConfiguration生成的RedisTemplate注入方法生成RedisCacheManager
RedisAutoConfiguration关键代码
@Configuration
@ConditionalOnClass({ JedisConnection.class, RedisOperations.class, Jedis.class })
@EnableConfigurationProperties(RedisProperties.class)
public class RedisAutoConfiguration {
/**
* Standard Redis configuration.
*/
@Configuration
protected static class RedisConfiguration {
….
@Bean
@ConditionalOnMissingBean(name = "redisTemplate")
public RedisTemplate<Object, Object> redisTemplate(
RedisConnectionFactory redisConnectionFactory)
throws UnknownHostException {
RedisTemplate<Object, Object> template = new RedisTemplate<Object, Object>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
@Bean
@ConditionalOnMissingBean(StringRedisTemplate.class)
public StringRedisTemplate stringRedisTemplate(
RedisConnectionFactory redisConnectionFactory)
throws UnknownHostException {
StringRedisTemplate template = new StringRedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
}
}
RedisCacheConfiguration关键代码
@Configuration
@AutoConfigureAfter(RedisAutoConfiguration.class)
@ConditionalOnBean(RedisTemplate.class)
@ConditionalOnMissingBean(CacheManager.class)
@Conditional(CacheCondition.class)
class RedisCacheConfiguration {
private final CacheProperties cacheProperties;
private final CacheManagerCustomizers customizerInvoker;
RedisCacheConfiguration(CacheProperties cacheProperties,
CacheManagerCustomizers customizerInvoker) {
this.cacheProperties = cacheProperties;
this.customizerInvoker = customizerInvoker;
}
@Bean
public RedisCacheManager cacheManager(RedisTemplate<Object, Object> redisTemplate) {
RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
cacheManager.setUsePrefix(true);
List<String> cacheNames = this.cacheProperties.getCacheNames();
if (!cacheNames.isEmpty()) {
cacheManager.setCacheNames(cacheNames);
}
return this.customizerInvoker.customize(cacheManager);
}
}
★RedisAutoConfiguration关键代码和RedisCacheConfiguration关键代码的分析
项目主启动类上被@SpringBootApplication注解,@SpringBootApplication又被@EnableAutoConfiguration注解。@EnableAutoConfiguration会触发扫描项目引入的jar包中的spring.factories文件,这样就会初始化类org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration。 RedisAutoConfiguration生成RedisTemplate。RedisCacheConfiguration通过类自身的cacheManager方法注入RedisTemplate并生成RedisCacheManager对象。
以上就是RedisCacheManager对象生成的过程。以下三点:
1)POM文件中引入spring-boot-starter-redis
2)主启动类上加上注解@EnableCaching
3)application.yml中的配置信息
这三点就能保证项目中引入Redis。RedisCacheManager对象由系统自动生成,自己也可以对RedisCacheManager对象做个性化的配置。
如何对RedisCacheManager做个性化的配置
个性化配置RedisCacheManager示例代码
@SpringBootApplication
@EnableCaching // 启动缓存
public class CacheApplication {
private static final Logger log = LoggerFactory.getLogger(CacheApplication.class);
public static void main(String[] args) {
log.info("Start CacheApplication.. ");
SpringApplication.run(CacheApplication.class, args);
}
/**
* 重新配置RedisCacheManager
* @param rd
*/
@Autowired
public void configRedisCacheManger(RedisCacheManager rd){
rd.setDefaultExpiration(100L);
}
}
分析
示例代码只是对key的有效期进行了配置。
也可以直接设计一个@Configuration注解的配置类,在其中使用@Bean注解生成一个RedisCacheManager类。系统也会采用自己写的这个RedisCacheManager。
★总结
Spring(SpringBoot)已经帮我们生成一个RedisCacheManager并进行了配置。我们再可以对这个RedisCacheManager进行二次配置。