文档章节

SpringBoot下Redis相关配置是如何被初始化的

k
 karma123
发布于 2018/07/17 14:00
字数 1635
阅读 502
收藏 2

参考网页

SpringBoot集成Redis的原理

https://blog.csdn.net/hry2015/article/details/74276423

https://blog.csdn.net/hry2015/article/details/75451705

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进行二次配置。

© 著作权归作者所有

共有 人打赏支持
k
粉丝 7
博文 88
码字总数 65057
作品 0
丰台
私信 提问
SpringBoot 学习二:操作数据库

本文将从以下几个方面介绍: 前言 配置数据源 SpringBoot 整合 Mybatis SpringBoot 整合 JdbcTemplate SpringBoot 整合 Redis 前言 在上篇文章 SpringBoot 学习一 中已经学习了 SpringBoot的...

tsmyk0715
2018/09/26
0
0
springboot集成redis

最近一直在学习Springboot,集成redis有些地方不明白,跟大家交流下 1. 在yml中配置了如下 连接信息,最简单的配置,springboot讲究去xml化通过配置类初始化, springmvc时,xml一般是 创建r...

樱木花道VS康
2018/06/26
129
0
恒宇少年/spring-boot-chapter

简书整套文档以及源码解析 专题 专题名称 专题描述 001 Spring Boot 核心技术 讲解SpringBoot一些企业级层面的核心组件 002 Spring Cloud 核心技术 对Spring Cloud核心技术全面讲解 003 Quer...

恒宇少年
2018/04/19
0
0
SpringBoot注解方式整合Redis--最简单的实例

参考网页 springboot中注解实现集成redis https://blog.csdn.net/a67474506/article/details/52608855 一些SpringBoot相关知识的讲解 SpringBoot开箱即用的体现--本质上是SpringBoot提前做好...

karma123
2018/07/04
0
0
【SpringBoot2.0系列08】SpringBoot之redis数据缓存管理

【SpringBoot2.0系列01】初识SpringBoot 【SpringBoot2.0系列02】SpringBoot之使用Thymeleaf视图模板 【SpringBoot2.0系列03】SpringBoot之使用freemark视图模板 【SpringBoot2.0系列04】Spr...

余空啊
2018/08/20
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Cookie 显示用户上次访问的时间

import javax.servlet.ServletException;import javax.servlet.annotation.WebServlet;import javax.servlet.http.Cookie;import javax.servlet.http.HttpServlet;import javax.serv......

gwl_
今天
1
0
网络编程

第14天 网络编程 今日内容介绍  网络通信协议  UDP通信  TCP通信 今日学习目标  能够辨别UDP和TCP协议特点  能够说出UDP协议下两个常用类名称  能够说出TCP协议下两个常用类名称...

stars永恒
今天
1
0
二进制相关

二进制 众所周知计算机使用的是二进制,数字的二进制是如何表示的呢? 实际就是逢二进一。比如 2 用二进制就是 10。那么根据此可以推算出 5的二进制等于 10*10+1 即为 101。 在计算机中,负数以...

NotFound403
昨天
3
0
day22:

1、写一个getinterface.sh 脚本可以接受选项[i,I],完成下面任务: 1)使用格式:getinterface.sh [-i interface | -I ip] 2)当用户使用-i选项时,显示指定网卡的IP地址;当用户使用-I选项...

芬野de博客
昨天
2
0
Spring Cloud Alibaba基础教程:使用Nacos实现服务注册与发现

自Spring Cloud Alibaba发布第一个Release以来,就备受国内开发者的高度关注。虽然Spring Cloud Alibaba还没能纳入Spring Cloud的主版本管理中,但是凭借阿里中间件团队的背景,还是得到不少...

程序猿DD
昨天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部