spring缓存的解析

源码分析

CacheAutoConfiguration

@Configuration
// 仅在类 CacheManager 存在时生效
@ConditionalOnClass(CacheManager.class)
// 仅在类型为  CacheAspectSupport 的 bean 存在时才生效
// 换句话讲,开发人员使用了 @EnableCaching 时才有效,因为注解 @EnableCaching 隐式导致了
// bean CacheInterceptor cacheInterceptor 的定义,而 CacheInterceptor 实现了接口 CacheAspectSupport
@ConditionalOnBean(CacheAspectSupport.class)
// 仅在类型为 CacheManager , 名称为 cacheResolver 的 bean 不存在时生效
@ConditionalOnMissingBean(value = CacheManager.class, name = "cacheResolver")
// 确保前缀为 spring.cache 的配置项加载到 bean CacheProperties
@EnableConfigurationProperties(CacheProperties.class)
// Spring Cache 自动配置机制必须在缓存数据基础设施自动配置应用之后进行
@AutoConfigureAfter({ CouchbaseAutoConfiguration.class, HazelcastAutoConfiguration.class,
		HibernateJpaAutoConfiguration.class, RedisAutoConfiguration.class })
// 导入 CacheConfigurationImportSelector   , 其实是导入 Spring Cache 使用的各类基础设置
// 的配置,比如 RedisCacheConfiguration , EhCacheCacheConfiguration , HazelcastCacheConfiguration,
// 这些配置会基于相应基础设施提供 bean cacheManager
@Import({CacheAutoConfiguration.CacheConfigurationImportSelector.class, CacheAutoConfiguration.CacheManagerEntityManagerFactoryDependsOnPostProcessor.class})
public class CacheAutoConfiguration {
    public CacheAutoConfiguration() {
    }

    // 定义 bean CacheManagerCustomizers cacheManagerCustomizers,
    // 基于容器中存在的 CacheManagerCustomizer bean 组件,可能有多个,将它们
    // 组合包装为一个类型为 CacheManagerCustomizers 的 bean 组件 
    // 缺省情况下,容器中没有 CacheManagerCustomizer bean 组件
    @Bean
    @ConditionalOnMissingBean
    public CacheManagerCustomizers cacheManagerCustomizers(ObjectProvider<CacheManagerCustomizer<?>> customizers) {
        return new CacheManagerCustomizers((List)customizers.orderedStream().collect(Collectors.toList()));
    }


    // 定义bean CacheManagerValidator cacheAutoConfigurationValidator,
    // 该 bean 存在的意义在于确保容器中存在 bean cacheManager, 从而确保
    // 缓存机制可以继续被配置和使用
    @Bean
    public CacheAutoConfiguration.CacheManagerValidator cacheAutoConfigurationValidator(CacheProperties cacheProperties, ObjectProvider<CacheManager> cacheManager) {
        return new CacheAutoConfiguration.CacheManagerValidator(cacheProperties, cacheManager);
    }


   	/**
	 * 把缓存的几种类型选择器添加到里面,有10种吧
	 * 默认SimpleCacheConfiguration自动配置
	 */
    static class CacheConfigurationImportSelector implements ImportSelector {
        CacheConfigurationImportSelector() {
        }

        public String[] selectImports(AnnotationMetadata importingClassMetadata) {
            CacheType[] types = CacheType.values();
            String[] imports = new String[types.length];

            for(int i = 0; i < types.length; ++i) {
                imports[i] = CacheConfigurations.getConfigurationClass(types[i]);
            }

            return imports;
        }
    }



	/**
	 * 校验自己的缓存配置是不是可用
	 */
    static class CacheManagerValidator implements InitializingBean {
        private final CacheProperties cacheProperties;
        private final ObjectProvider<CacheManager> cacheManager;

        CacheManagerValidator(CacheProperties cacheProperties, ObjectProvider<CacheManager> cacheManager) {
            this.cacheProperties = cacheProperties;
            this.cacheManager = cacheManager;
        }

        public void afterPropertiesSet() {
            Assert.notNull(this.cacheManager.getIfAvailable(), () -> {
                return "No cache manager could be auto-configured, check your configuration (caching type is '" + this.cacheProperties.getType() + "')";
            });
        }
    }


    // 如果 bean AbstractEntityManagerFactoryBean 存在才生效    
    // 该配置同时是一个 EntityManagerFactoryDependsOnPostProcessor ,
    // 它动态声明了所有类型为 EntityManagerFactory 的 bean 都必须依赖于
    // 名称为 cacheManager 的 bean 
    @ConditionalOnClass({LocalContainerEntityManagerFactoryBean.class})
    @ConditionalOnBean({AbstractEntityManagerFactoryBean.class})
    static class CacheManagerEntityManagerFactoryDependsOnPostProcessor extends EntityManagerFactoryDependsOnPostProcessor {
        CacheManagerEntityManagerFactoryDependsOnPostProcessor() {
            super(new String[]{"cacheManager"});
        }
    }
}

看的头晕不晕???
至于为什么是SimpleCacheConfiguration自动配置缓存
看一下他的源码

SimpleCacheConfiguration

@Configuration(
    proxyBeanMethods = false
)
@ConditionalOnMissingBean({CacheManager.class})//如果没有缓存管理器的bean才会启动
@Conditional({CacheCondition.class})//如果符合这个条件才会实现
class SimpleCacheConfiguration {
    SimpleCacheConfiguration() {
    }

    @Bean //返回自己的缓存管理器
    ConcurrentMapCacheManager cacheManager(CacheProperties cacheProperties, CacheManagerCustomizers cacheManagerCustomizers) {
        ConcurrentMapCacheManager cacheManager = new ConcurrentMapCacheManager();
        List<String> cacheNames = cacheProperties.getCacheNames();
        if (!cacheNames.isEmpty()) {
            cacheManager.setCacheNames(cacheNames);
        }

        return (ConcurrentMapCacheManager)cacheManagerCustomizers.customize(cacheManager);
    }
}

看起来也很简单
只要符合这两个条件
他就会自动生效
那么如果我们不想用他默认的实现方式
比如想用redis用缓存怎么办
看一看redis的自动缓存的源码

RedisCacheConfiguration

@Configuration(
    proxyBeanMethods = false
)
@ConditionalOnClass({RedisConnectionFactory.class})//存在这个类生效
@AutoConfigureAfter({RedisAutoConfiguration.class})
@ConditionalOnBean({RedisConnectionFactory.class})//存在这个bean生效
@ConditionalOnMissingBean({CacheManager.class})
@Conditional({CacheCondition.class})
class RedisCacheConfiguration {
    RedisCacheConfiguration() {
    }

    @Bean
    RedisCacheManager cacheManager(CacheProperties cacheProperties, CacheManagerCustomizers cacheManagerCustomizers, ObjectProvider<org.springframework.data.redis.cache.RedisCacheConfiguration> redisCacheConfiguration, ObjectProvider<RedisCacheManagerBuilderCustomizer> redisCacheManagerBuilderCustomizers, RedisConnectionFactory redisConnectionFactory, ResourceLoader resourceLoader) {
        RedisCacheManagerBuilder builder = RedisCacheManager.builder(redisConnectionFactory).cacheDefaults(this.determineConfiguration(cacheProperties, redisCacheConfiguration, resourceLoader.getClassLoader()));
        List<String> cacheNames = cacheProperties.getCacheNames();
        if (!cacheNames.isEmpty()) {
            builder.initialCacheNames(new LinkedHashSet(cacheNames));
        }

        redisCacheManagerBuilderCustomizers.orderedStream().forEach((customizer) -> {
            customizer.customize(builder);
        });
        return (RedisCacheManager)cacheManagerCustomizers.customize(builder.build());
    }

    private org.springframework.data.redis.cache.RedisCacheConfiguration determineConfiguration(CacheProperties cacheProperties, ObjectProvider<org.springframework.data.redis.cache.RedisCacheConfiguration> redisCacheConfiguration, ClassLoader classLoader) {
        return (org.springframework.data.redis.cache.RedisCacheConfiguration)redisCacheConfiguration.getIfAvailable(() -> {
            return this.createConfiguration(cacheProperties, classLoader);
        });
    }

    private org.springframework.data.redis.cache.RedisCacheConfiguration createConfiguration(CacheProperties cacheProperties, ClassLoader classLoader) {
        Redis redisProperties = cacheProperties.getRedis();
        org.springframework.data.redis.cache.RedisCacheConfiguration config = org.springframework.data.redis.cache.RedisCacheConfiguration.defaultCacheConfig();
        config = config.serializeValuesWith(SerializationPair.fromSerializer(new JdkSerializationRedisSerializer(classLoader)));
        if (redisProperties.getTimeToLive() != null) {
            config = config.entryTtl(redisProperties.getTimeToLive());
        }

        if (redisProperties.getKeyPrefix() != null) {
            config = config.prefixKeysWith(redisProperties.getKeyPrefix());
        }

        if (!redisProperties.isCacheNullValues()) {
            config = config.disableCachingNullValues();
        }

        if (!redisProperties.isUseKeyPrefix()) {
            config = config.disableKeyPrefix();
        }

        return config;
    }
}

相比SimpleCacheConfiguration之下,发现多了3个注解
@ConditionalOnClass({RedisConnectionFactory.class})
@AutoConfigureAfter({RedisAutoConfiguration.class})
@ConditionalOnBean({RedisConnectionFactory.class})
看名字就知道要用Redis连接工厂
点进去看看RedisConnectionFactory这个是什么

public interface RedisConnectionFactory extends PersistenceExceptionTranslator {
    RedisConnection getConnection();

    RedisClusterConnection getClusterConnection();

    boolean getConvertPipelineAndTxResults();

    RedisSentinelConnection getSentinelConnection();
}

也就是一些接口获取连接的等等
所以我们只要导入了这个

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
            <version>2.2.2.RELEASE</version>
        </dependency>

配置了

spring:
  redis:
    host: 192.168.1.109
    port: 6379

总结

也就会匹配redis使用redis做缓存
如果你导入了多个组件做缓存的话
可能你就需要自己配置bean
使用哪个生效

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值