All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.zodiac.autoconfigure.redis.RedisCacheAutoConfiguration Maven / Gradle / Ivy

There is a newer version: 1.6.8
Show newest version
package org.zodiac.autoconfigure.redis;

import java.io.IOException;
import java.time.Duration;
import java.util.Objects;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.core.env.Environment;
import org.zodiac.autoconfigure.cache.CaffeineProperties;
import org.zodiac.autoconfigure.redis.condition.ConditionalOnRedisEnabled;
import org.zodiac.commons.constants.SystemPropertiesConstants;
import org.zodiac.commons.util.Networks;

@SpringBootConfiguration
@ConditionalOnRedisEnabled
@AutoConfigureAfter(value = {CacheAutoConfiguration.class})
@EnableConfigurationProperties(value = {RedisProperties.class})
@ConditionalOnClass(value = {org.zodiac.redis.jedis.JedisPostProcessor.class, org.springframework.data.redis.core.RedisTemplate.class})
public class RedisCacheAutoConfiguration {

    protected static final Logger LOGGER = LoggerFactory.getLogger(RedisCacheAutoConfiguration.class);

    public RedisCacheAutoConfiguration() {
        super();
    }

    @SpringBootConfiguration
    @ConditionalOnRedisEnabled
    @ConditionalOnBean(value = {org.springframework.data.redis.core.RedisTemplate.class})
    @EnableConfigurationProperties(value = {CaffeineProperties.class})
    @ConditionalOnClass(value = {com.github.benmanes.caffeine.cache.Cache.class, redis.clients.jedis.Jedis.class})
    protected static class JedisCaffeineAutoConfiguration {

        private Environment environment;
        private ConfigurableListableBeanFactory beanFactory;
        private CaffeineProperties caffeineProperties;

        public JedisCaffeineAutoConfiguration(Environment environment, ConfigurableListableBeanFactory beanFactory,
            CaffeineProperties caffeineProperties) {
            this.environment = environment;
            this.beanFactory = beanFactory;
            this.caffeineProperties = caffeineProperties;
        }

        @Bean
        @ConditionalOnMissingBean
        @ConditionalOnClass(value = {redis.clients.jedis.Jedis.class})
        @ConfigurationProperties(prefix = SystemPropertiesConstants.Zodiac.SPRING_REDIS_CACHE_CLOUD_JEDIS_PREFIX,
            ignoreInvalidFields = true)
        protected RedisCacheCloudListProperties cacheCloudListProperties() {
            return new RedisCacheCloudListProperties();
        }

        @Bean
        @ConditionalOnMissingBean
        protected org.zodiac.redis.jedis.JedisPostProcessor jedisPostProcessor(RedisCacheCloudListProperties cacheCloudListPropertie) {
            return new org.zodiac.redis.jedis.JedisPostProcessor(cacheCloudListPropertie, false, environment).process(beanFactory);
        }

        @Bean(value = org.zodiac.redis.constants.RedisConstants.DEFAULT_CACHE_MANAGER_BEAN_NAME)
        @ConditionalOnMissingBean
        @ConditionalOnClass(value = {redis.clients.jedis.Jedis.class})
        protected org.springframework.cache.CacheManager jedisCacheManager(org.springframework.data.redis.core.RedisTemplate redisTemplate,
            org.springframework.data.redis.connection.jedis.JedisConnectionFactory jedisConnectionFactory) {
            if (caffeineProperties.isSecondLevelCache()) {
                return new org.zodiac.redis.jedis.JedisSecondLevelCacheManager(caffeineProperties, redisTemplate);
            } else {
                return org.springframework.data.redis.cache.RedisCacheManager.builder(jedisConnectionFactory)
                    .cacheDefaults(org.springframework.data.redis.cache.RedisCacheConfiguration.defaultCacheConfig()
                        .entryTtl(Duration.ofMillis(caffeineProperties.getRemote().getGlobalExpiration()))
                        .serializeKeysWith(org.springframework.data.redis.serializer.RedisSerializationContext.SerializationPair.fromSerializer(keySerializer()))
                        .serializeValuesWith(
                            org.springframework.data.redis.serializer.RedisSerializationContext.SerializationPair.fromSerializer(valueSerializer())))
                    .transactionAware().build();
            }
        }

        @Bean
        @ConditionalOnMissingBean
        @ConditionalOnBean(value = {org.zodiac.redis.jedis.JedisSecondLevelCacheManager.class})
        @ConditionalOnClass(value = {redis.clients.jedis.Jedis.class})
        protected org.springframework.data.redis.listener.RedisMessageListenerContainer redisMessageListenerContainer(
            org.zodiac.redis.jedis.JedisSecondLevelCacheManager jedisSencondLevelCacheManager, org.springframework.data.redis.core.RedisTemplate redisTemplate) {
            org.springframework.data.redis.listener.RedisMessageListenerContainer redisMessageListenerContainer = new org.springframework.data.redis.listener.RedisMessageListenerContainer();
            redisMessageListenerContainer.setConnectionFactory(redisTemplate.getConnectionFactory());
            redisMessageListenerContainer.addMessageListener((message, pattern) -> {
                org.zodiac.redis.queue.model.QueueCacheMessage cacheMessage =
                    (org.zodiac.redis.queue.model.QueueCacheMessage)redisTemplate.getValueSerializer().deserialize(message.getBody());
                LOGGER.debug("Recevice a jedis topic message, clear local cache, the cacheName is {}, the key is {} .",
                    cacheMessage.getCacheName(), cacheMessage.getKey());
                if (Objects.equals(cacheMessage.getHostname(), Networks.LOCAL_HOSTNAME)) {
                    RedisCacheAutoConfiguration.LOGGER.debug(
                        "Skip a jedis topic message that clear itself local cache, the cacheName is {}, the key is {} .",
                        cacheMessage.getCacheName(), cacheMessage.getKey());
                    return;
                }
                jedisSencondLevelCacheManager.clearLocalCache(cacheMessage.getCacheName(), cacheMessage.getKey());
            }, new org.springframework.data.redis.listener.ChannelTopic(caffeineProperties.getRemote().getTopic()));
            return redisMessageListenerContainer;
        }

        private org.springframework.data.redis.serializer.RedisSerializer keySerializer() {
            return new org.springframework.data.redis.serializer.StringRedisSerializer();
        }

        private org.springframework.data.redis.serializer.RedisSerializer valueSerializer() {
            return new org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer();
        }
    }

    @SpringBootConfiguration
    @ConditionalOnRedisEnabled
    @ConditionalOnBean(value = {org.redisson.api.RedissonClient.class})
    @EnableConfigurationProperties(value = {CaffeineProperties.class})
    @ConditionalOnClass(value = {com.github.benmanes.caffeine.cache.Cache.class, org.redisson.api.RedissonClient.class})
    protected static class RedissonCaffeineAutoConfiguration {

        private Environment environment;
        private ConfigurableListableBeanFactory beanFactory;
        private CaffeineProperties caffeineProperties;

        public RedissonCaffeineAutoConfiguration(Environment environment, ConfigurableListableBeanFactory beanFactory,
            CaffeineProperties caffeineProperties) {
            this.environment = environment;
            this.beanFactory = beanFactory;
            this.caffeineProperties = caffeineProperties;
        }

        @Bean
        @ConditionalOnMissingBean
        @ConditionalOnClass(value = {org.redisson.api.RedissonClient.class})
        @ConfigurationProperties(prefix = SystemPropertiesConstants.Zodiac.SPRING_REDIS_CACHE_CLOUD_REDISSON_PREFIX,
            ignoreInvalidFields = true)
        protected RedissonListProperties cacheCloudListProperties() {
            return new RedissonListProperties();
        }

        @Bean
        @ConditionalOnMissingBean
        protected org.zodiac.redis.redisson.RedissonPostProcessor redissonPostProcessor(RedissonListProperties cacheCloudListProperties)
            throws RuntimeException, IOException {
            return new org.zodiac.redis.redisson.RedissonPostProcessor(cacheCloudListProperties, environment).process(beanFactory);
        }

        @Bean(value = org.zodiac.redis.constants.RedisConstants.DEFAULT_CACHE_MANAGER_BEAN_NAME)
        @ConditionalOnMissingBean
        @ConditionalOnClass(value = {org.redisson.api.RedissonClient.class, org.redisson.spring.cache.RedissonSpringCacheManager.class})
        protected org.springframework.cache.CacheManager redissonCacheManager(org.redisson.api.RedissonClient redissonClient) {
            if (caffeineProperties.isSecondLevelCache()) {
                return new org.zodiac.redis.redisson.RedissionSecondLevelCacheManager(caffeineProperties, redissonClient);
            } else {
                return new org.redisson.spring.cache.RedissonSpringCacheManager(redissonClient);
            }
        }

        @Bean
        @ConditionalOnClass(value = {org.redisson.api.RedissonClient.class})
        @ConditionalOnBean(value = {org.zodiac.redis.redisson.RedissionSecondLevelCacheManager.class})
        protected org.zodiac.redis.redisson.RedissonMessageListenerContainer redissonMessageListenerContainer(
            org.zodiac.redis.redisson.RedissionSecondLevelCacheManager cacheManager, org.redisson.api.RedissonClient redissonClient) {
            org.zodiac.redis.redisson.RedissonMessageListenerContainer container = new org.zodiac.redis.redisson.RedissonMessageListenerContainer();
            container.setRedissonClient(redissonClient);
            container.addMessageListener(message -> {
                LOGGER.debug("Recevice a redisson topic message, clear local cache, the cacheName is {}, the key is {} .",
                    message.getCacheName(), message.getKey());
                if (Objects.equals(message.getHostname(), Networks.LOCAL_HOSTNAME)) {
                    RedisCacheAutoConfiguration.LOGGER.debug(
                        "Skip a redisson topic message that clear itself local cache, the cacheName is {}, the key is {} .",
                        message.getCacheName(), message.getKey());
                    return;
                }
                cacheManager.clearLocalCache(message.getCacheName(), message.getKey());
            }, caffeineProperties.getRemote().getTopic());
            return container;
        }
    }
}