从零开始学习SpringBootSpring Boot

SpringBoot - 默认缓存配置以及运行流程

2018-05-30  本文已影响8人  BzCoder

今天来学习下SpringBoot中的缓存。

一.HelloWorld

在SpringBoot开启缓存功能非常简单,只需要三步,就可以了,我们可以通过是否输出文字来判断程序是否查询了数据库。

  1. 引入MAVEN
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>
  1. 增加配置注解@EnableCaching
@SpringBootApplication
@EnableCaching
public class CacheApplication {

    public static void main(String[] args) {
        SpringApplication.run(CacheApplication.class, args);
    }
}
  1. 增加缓存注解 @Cacheable
package com.example.cache.service;

import com.example.cache.bean.Employee;
import com.example.cache.mapper.EmployeeMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

/**
 * @author BaoZhou
 * @date 2018/5/29
 */
@Service
public class EmployeeService {
    @Autowired
    private EmployeeMapper mapper;
    @Cacheable(cacheNames = {"empCache"} )
    public Employee getEmp(Integer id) {
        System.out.println("查询了查询了");
        return mapper.getEmpById(id);
    }
}

二.SpringBoot默认缓存配置原理

说到原理,我们就又要看自动配置文件了。打开CacheAutoConfiguration类。

/**
 * {@link EnableAutoConfiguration Auto-configuration} for the cache abstraction. Creates a
 * {@link CacheManager} if necessary when caching is enabled via {@link EnableCaching}.
 * <p>
 * Cache store can be auto-detected or specified explicitly via configuration.
 *
 * @author Stephane Nicoll
 * @since 1.3.0
 * @see EnableCaching
 */
@Configuration
@ConditionalOnClass(CacheManager.class)
@ConditionalOnBean(CacheAspectSupport.class)
@ConditionalOnMissingBean(value = CacheManager.class, name = "cacheResolver")
@EnableConfigurationProperties(CacheProperties.class)
@AutoConfigureBefore(HibernateJpaAutoConfiguration.class)
@AutoConfigureAfter({ CouchbaseAutoConfiguration.class, HazelcastAutoConfiguration.class,
        RedisAutoConfiguration.class })
@Import(CacheConfigurationImportSelector.class)
public class CacheAutoConfiguration {
...
}

从头部注释可以看到,我们需要用@EnableCaching让自动配置类生效。 接下来我们看CacheConfigurationImportSelector.class,从命名上可以了解,这是引入不同的缓存配置类的选择器,打上断点发现容器中包含各种缓存的配置。

0 = "org.springframework.boot.autoconfigure.cache.GenericCacheConfiguration"
1 = "org.springframework.boot.autoconfigure.cache.JCacheCacheConfiguration"
2 = "org.springframework.boot.autoconfigure.cache.EhCacheCacheConfiguration"
3 = "org.springframework.boot.autoconfigure.cache.HazelcastCacheConfiguration"
4 = "org.springframework.boot.autoconfigure.cache.InfinispanCacheConfiguration"
5 = "org.springframework.boot.autoconfigure.cache.CouchbaseCacheConfiguration"
6 = "org.springframework.boot.autoconfigure.cache.RedisCacheConfiguration"
7 = "org.springframework.boot.autoconfigure.cache.CaffeineCacheConfiguration"
8 = "org.springframework.boot.autoconfigure.cache.SimpleCacheConfiguration"
9 = "org.springframework.boot.autoconfigure.cache.NoOpCacheConfiguration"

我们打开DEBUG后运行后,在LOG中我们可以看到SimpleCacheConfiguration matched,所以当不配置时默认选择的是SimpleCacheConfiguration。


SimpleCacheConfiguration

SimpleCacheConfiguration向容器中添加一个cacheManager。

@Configuration
@ConditionalOnMissingBean(CacheManager.class)
@Conditional(CacheCondition.class)
class SimpleCacheConfiguration {

    private final CacheProperties cacheProperties;

    private final CacheManagerCustomizers customizerInvoker;

    SimpleCacheConfiguration(CacheProperties cacheProperties,
            CacheManagerCustomizers customizerInvoker) {
        this.cacheProperties = cacheProperties;
        this.customizerInvoker = customizerInvoker;
    }

    @Bean
    public ConcurrentMapCacheManager cacheManager() {
        ConcurrentMapCacheManager cacheManager = new ConcurrentMapCacheManager();
        List<String> cacheNames = this.cacheProperties.getCacheNames();
        if (!cacheNames.isEmpty()) {
            cacheManager.setCacheNames(cacheNames);
        }
        return this.customizerInvoker.customize(cacheManager);
    }

}

而cacheManager是一个ConcurrentMapCacheManager类型的,其中包含了cache的基本操作,默认是使用ConcurrentHashMap来管理缓存。

@Override
    @Nullable
    public Cache getCache(String name) {
        Cache cache = this.cacheMap.get(name);
        if (cache == null && this.dynamic) {
            synchronized (this.cacheMap) {
                cache = this.cacheMap.get(name);
                if (cache == null) {
                    cache = createConcurrentMapCache(name);
                    this.cacheMap.put(name, cache);
                }
            }
        }
        return cache;
    }

而KEY的生成默认使用SimpleKeyGenerator。

/**
     * Generate a key based on the specified parameters.
     */
    public static Object generateKey(Object... params) {
        if (params.length == 0) {
            return SimpleKey.EMPTY;
        }
        if (params.length == 1) {
            Object param = params[0];
            if (param != null && !param.getClass().isArray()) {
                return param;
            }
        }
        return new SimpleKey(params);
    }

SimpleKeyGenerator是在CacheAspectSupport中定义的。CacheInterceptor是CacheAspectSupport的实现类。而CacheInterceptor最终是在CacheProxyFactoryBean中定义的。CacheProxyFactoryBean应该是在SpringBoot配置中已经注入。

那么有关于SpringBoot默认缓存配置以及运行流程就讲到这里。

上一篇 下一篇

猜你喜欢

热点阅读