Spring Cache using layman's language and integration (with source code parsing)

Spring Cache using layman's language and integration (with source code parsing)

Personal Development Environment

java environment: Jdk1.8.0_60

Compiler: IntelliJ IDEA 2019.1

springCache official document: https://docs.spring.io/spring/docs/5.1.9.RELEASE/spring-framework-reference/integration.html#cache

A, Spring cache abstraction

In fact, with the generated background SpringCache background Spring produced somewhat similar. Since Java EE framework bloated, inefficient, low observability of code, object creation and complex dependencies, Spring framework came out, essentially, all of the projects are inseparable from Java background Spring or SpringBoot (further simplify the packaging of Spring) . High concurrency problems now facing the project more and more kinds of caching applications also increased, so in general the Spring Framework, you need to have a more convenient and simple way to complete cache support.
SpringCache itself is an abstract realization of a caching system, and no specific cache capacity, to use SpringCache also need to meet the specific cache implementation to complete.

  • Cache interface specification is defined as the assembly cache, the cache comprising a set of various operations;
  • Cache interface provides an implementation of the various Spring xxxCache; if RedisCache, EhCacheCache, ConcurrentMapCache the like;

Second, important notes, parameters

name Explanation
Cache Cache interface, defined cache operations. Realize there: RedisCache, EhCacheCache, ConcurrentMapCache etc.
CacheManager Cache manager, manage cache (Cache) component
@Cacheable The main method for the configuration can be cached in accordance with a request parameter method
@CacheEvict Empty the cache
@CachePut Ensure the method is called, and hope the results are cached. The difference is whether the @Cacheable are calling each method, commonly used in the update
@EnableCaching Open annotation-based caching
keyGenerator key generation strategy when cache data
serialize Cache data value when serialization strategy
@CacheConfig Unified cache configuration properties of this class of notes

@ Cacheable / @ CachePut / @ CacheEvict main parameters

name Explanation
value Cache name, defined in the spring configuration file must specify at least one example: @Cacheable (value = "mycache") or @Cacheable (value = { "cache1", "cache2"}
key Cache key, can be empty, if you want to specify SpEL prepared in accordance with the expression, if not specified, the default parameters are combined for example in accordance with all methods: @Cacheable (value = "testcache", key = "# id")
condition Buffer conditions, can be empty, the SpEL written, returns true or false, it is true only cache / cache clear example: @Cacheable (value = "testcache", condition = "# userName.length ()> 2")
unless Negative caching. When the result of the condition is TRUE, it will not be cached. @Cacheable (value = "testcache", unless = "# userName.length ()> 2")
allEntries (@CacheEvict) Whether to clear all cache content, the default is false, if you specify true, the method call will immediately clear all cache for example: @CachEvict (value = "testcache", allEntries = true)
beforeInvocation (@CacheEvict) Whether it is emptied before the execution method, the default is false, if you specify is true, when the method has not been performed on empty the cache, by default, if the execution method throws an exception, it is not clear the cache for example: @ CachEvict (value = "testcache", beforeInvocation = true)

Three, SpEL context data

Spring Cache SpEL provides some context for the data we use, the table is drawn directly from Spring official document:

name position description Examples
methodName the root object The current method is called name #root.methodname
method the root object The current method is called #root.method.name
target the root object The current target object is called an instance #root.target
targetClass the root object The current class is called the target object #root.targetClass
args the root object Parameter list is called the current method #root.args[0]
caches the root object The current method calls use the cache list #root.caches[0].name
Argument Name Execution Context Parameters of the method is called a current, such as findArtisan (Artisan artisan), the parameters can be obtained by artsian.id # #artsian.id
result Execution Context The return value after execution of the method (only effective method for performing the determination, unless cacheEvict as the beforeInvocation = false) #result

Fourth, real

1. Import dependence

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>

2. Start class open the cache comment @EnableCaching

/**
 * 1、开启基于注解的缓存 @EnableCaching
 * 2、标注缓存注解即可
 *    @Cacheable
 *    @CacheEvict
 *    @CachePut
 */
@SpringBootApplication
@EnableCaching  //开启缓存
public class CacheApplication{
    public static void main(String[] args) {
        SpringApplication.run(CacheApplication.class, args);
    }

}

3. Cache @Cacheable

Running processes :

@CacheableBefore running the method, go to the query Cache (cache component), acquired in accordance with cacheNames / value specified name, if not first obtain the cache Cache component automatically created.

Source analysis :

public @interface Cacheable {
    // cacheNames/value:指定缓存组件的名字;将方法的返回结果放在哪个缓存中,是数组的方式,可以指定多个缓存
    @AliasFor("cacheNames")
    String[] value() default {};
    @AliasFor("value")
    String[] cacheNames() default {};

    // 缓存数据使用的key;可以用它来指定。默认是使用方法参数的值
    String key() default "";

    // key的生成器;可以自己指定key的生成器的组件id,key/keyGenerator:二选一使用;
    String keyGenerator() default "";

    // 指定缓存管理器;或者cacheResolver指定获取解析器 作用得到缓存集合
    String cacheManager() default "";
    String cacheResolver() default "";

    // 条件符合则缓存,编写SpEL:condition = "#a0>1":第一个参数的值大于1的时候才进行缓存
    String condition() default "";
    
    // 条件符合则不缓存,编写SpEL:unless = "#a0==2":如果第一个参数的值是2,结果不缓存;
    String unless() default "";

    // 是否使用异步模式,是否启用异步模式
    boolean sync() default false;
}

Drill bit :

@Cacheable(value = "emp" ,key = "targetClass + methodName +#p0")
public Employee getEmp(Integer id){
    System.out.println("查询"+id+"号员工");
    Employee emp = employeeMapper.getEmpById(id);
    return emp;
}

Stepped pit :

1, the property value/cacheNamesis required, and it specifies the cache stored in a piece of your namespace.

2、属性key是使用的spEL表达式

注意:踩坑,如果你把methodName换成method运行会报错,观察它们的返回类型,原因在于methodNameStringmethohMethod

Employee实体类一定要实现序列化public class Employee implements Serializable,否则会报java.io.NotSerializableException异常。

4.更新 @CachePut

@CachePut既调用方法,又更新缓存数据;同步更新缓存。简单来说就是用户修改数据同步更新缓存数据。

源码分析:(皮一下,去事故与@Cacheable相同,不做过多解释了,狗头护体~~~)

public @interface CachePut {
    
    @AliasFor("cacheNames")
    String[] value() default {};
    
    @AliasFor("value")
    String[] cacheNames() default {};

    String key() default "";

    String keyGenerator() default "";

    String cacheManager() default "";

    String cacheResolver() default "";

    String condition() default "";

    String unless() default "";
}

操练一下

注意该注解的value/cahceNameskey 必须与要更新的缓存相同,也就是与@Cacheable 相同。

@CachePut(value = "emp" ,key = "#employee.id")
public Employee updateEmp(Employee employee){
    System.out.println("updateEmp:"+employee);
    employeeMapper.updateEmp(employee);
    return employee;
}

5.清除 @CacheEvict

@CachEvict 的作用 主要针对方法配置,能够根据一定的条件对缓存进行清空 。

源码分析

public @interface CacheEvict {
    // 同上同上同上
    @AliasFor("cacheNames")
    String[] value() default {};
    @AliasFor("value")
    String[] cacheNames() default {};
    String key() default "";
    String keyGenerator() default "";
    String cacheManager() default "";
    String cacheResolver() default "";
    String condition() default "";

    // 指定清除这个缓存中所有的数据,示例:@CachEvict(value=”emp”,allEntries=true)
    boolean allEntries() default false;

    /*
     * 示例: @CachEvict(value=”emp”,beforeInvocation=true)
     * 代表清除缓存操作是在方法运行之前执行,无论方法是否出现异常,缓存都清除
     *
     * 示例: @CachEvict(value=”emp”,beforeInvocation=false)(默认)
     * 缓存的清除是否在方法之前执行 , 默认代表缓存清除操作是在方法执行之后执行;如果出现异常缓存就不会清除
     */
    boolean beforeInvocation() default false;
}

操练一下

//方法调用后清空所有缓存
@CacheEvict(value="accountCache", allEntries=true)
public void deleteEmp() {
    employeeMapper.deleteAll();
}

6.组合 @Caching

有时候我们可能组合多个Cache注解使用,此时就需要@Caching组合多个注解标签了。

源码分析

public @interface Caching {
    // 用于指定多个缓存设置操作
    Cacheable[] cacheable() default {};
    
    // 用于指定多个缓存更新操作
    CachePut[] put() default {};
    
    // 用于指定多个缓存失效操作
    CacheEvict[] evict() default {};
}

操练一下

// @Caching 定义复杂的缓存规则
@Caching(
    cacheable = {
        @Cacheable(value="emp",key = "#lastName")
    },
    put = {
        @CachePut(value="emp",key = "#result.id"),
        @CachePut(value="emp",key = "#result.email")
    }
)
public Employee getEmpByLastName(String lastName){
    return employeeMapper.getEmpByLastName(lastName);
}

7.全局配置 @CacheConfig

当我们需要缓存的地方越来越多,可以使用@CacheConfig(cacheNames = {"emp"})注解来统一指定value的值,这时可省略value,如果你在你的方法依旧写上了value,那么依然以方法的value值为准。

源码分析

public @interface Caching {
    // 用于指定多个缓存设置操作
    Cacheable[] cacheable() default {};
    
    // 用于指定多个缓存更新操作
    CachePut[] put() default {};
    
    // 用于指定多个缓存失效操作
    CacheEvict[] evict() default {};
}

操练一下

@CacheConfig(cacheNames = {"emp"}, /*keyGenerator = "cacheKeyGenerator"*/)
public class EmployeeServiceImpl implements EmployeeService {
    @Override
    @Cacheable(/*value = ‘emp’*/ key = "targetClass + methodName +#p0")
    public Employee getEmp(Integer id){
        Employee emp = employeeMapper.getEmpById(id);
        return emp;
    }
}

8.主键生成策略 keyGenerator

操练一下

创建CacheConfig配置类

@Configuration
public class CacheConfig {

    /**
     * 生成缓存主键策略 (方法名+参数)
     * 
     * @return KeyGenerator
     */
    @Bean("cacheKeyGenerator")
    public KeyGenerator keyGenerator() {
        return (target, method, params) -> (method.getName() + " [ " + Arrays.asList(params) + " ]");
    }
}

可以在@CacheConfig指定生成策略,也可以在@Cacheable/@CachePut/@CacheEvict指定key生成策略

@CacheConfig(cacheNames = {"emp"}, keyGenerator = "cacheKeyGenerator")
public class EmployeeServiceImpl implements EmployeeService {
    @Override
    @Cacheable(/*value = ‘emp’,keyGenerator = "cacheKeyGenerator"*/)
    public Employee getEmp(Integer id){
        Employee emp = employeeMapper.getEmpById(id);
        return emp;
    }
}

Guess you like

Origin www.cnblogs.com/yoci/p/11595226.html