package com.elab.redis.config;

import com.elab.redis.CacheTemplate;
import com.elab.redis.annotation.CacheLoopSubmit;
import com.elab.redis.interceptor.BeanFactoryCacheAttributeSourceAdvisor;
import com.elab.redis.interceptor.CacheAttributeSourcePointcut;
import com.elab.redis.interceptor.CacheInterceptor;
import com.elab.redis.spring.data.RedisTemplateDecorator;
import org.redisson.api.RedissonClient;
import org.redisson.spring.cache.RedissonSpringCacheManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.cache.CacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Role;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;

/**
 * 缓存自动配置
 *
 * @author ： liukx
 * @time ： 2020/7/8 - 19:12
 */
@Configuration
@ComponentScan(value = {"com.elab.redis.interceptor.impl"})
public class CacheAutoConfiguration {


    @Bean
    public CacheTemplate cacheTemplate(@Autowired RedissonClient redissonClient, @Autowired RedisTemplate<Object,
            Object> redisTemplate) {
        CacheTemplate cacheTemplate = new CacheTemplate();
        cacheTemplate.setRedissonClient(redissonClient);
        cacheTemplate.setRedisTemplate(redisTemplate);
        return cacheTemplate;
    }

    @Bean
    public RedisTemplate<Object, Object> redisTemplate(
            RedisConnectionFactory redisConnectionFactory) throws Exception {
        RedisTemplate<Object, Object> template = new RedisTemplateDecorator<>();
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }

    @Bean
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public BeanFactoryCacheAttributeSourceAdvisor transactionAdvisor() {
        BeanFactoryCacheAttributeSourceAdvisor advisor = new BeanFactoryCacheAttributeSourceAdvisor();
        advisor.setAdvice(transactionInterceptor());
        advisor.setPointcut(cacheAttributeSourcePointcut());
        return advisor;
    }

    @Bean
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public CacheAttributeSourcePointcut cacheAttributeSourcePointcut() {
        CacheAttributeSourcePointcut cacheAttributeSourcePointcut = new CacheAttributeSourcePointcut();
        cacheAttributeSourcePointcut.addAnnotations(CacheLoopSubmit.class);
        return cacheAttributeSourcePointcut;
    }

    @Bean
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public CacheInterceptor transactionInterceptor() {
        CacheInterceptor interceptor = new CacheInterceptor();
        return interceptor;
    }

    @Bean
    CacheManager cacheManager(RedissonClient redissonClient) {
        return new RedissonSpringCacheManager(redissonClient);
    }

}
