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

參考網頁

SpringBoot集成Redis的原理java

https://blog.csdn.net/hry2015/article/details/74276423程序員

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

application.yml配置文件中的屬性是如何讀入到程序中的?

RedisProperties類(org.springframework.boot.autoconfigure.data.redis.RedisProperties

application.properties配置參數示例

spring.redis.database=0spring

spring.redis.host=192.168.188.7數據庫

spring.redis.password=123緩存

spring.redis.port=6379springboot

spring.redis.pool.max-idle=8app

spring.redis.pool.min-idle=0  spring-boot

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

相關文章
相關標籤/搜索