源码分析
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
使用哪个生效