Spring cache缓存注解@Cacheable、@CacheEvict、@CachePut详解


Spring提供注解来支持Spring cache。Spring cache是作用在方法上的,当调用一个缓存方法时,会把该方法的参数和结果作为一个键值对存放在缓存中,等到下次利用同样的参数来调用该方法时,就不再执行该方法,而是从缓存直接返回。

一、@Cacheable

@Cacheable可以标记在一个类上,也可以标记在一个方法上。标记在一个类上,则表明该类的所有方法都是支持缓存的。Spring在缓存方法的返回值都是以键值对进行缓存的,值就是方法的返回结果,至于key的话,Spring支持两种策略,默认策略和自定义策略。
注意:当一个支持缓存的方法在对象内部被调用是不会触发缓存功能的。
@Cacheable可以指定三个属性,value、key和condition

1.1 value属性

value属性指定cache名称,表示当前方法是会被缓存在哪个cache上,对应cache的名称。其可以是一个cache也可以是多个cache,当需要指定多个cache时是一个数组。

@Cacheable(value = "getConfCustomer",unless="#result == null") // Cache是发生在getConfCustomer上的
    public ConfCustomerInfoVo getConfCustomer(String confCustomerCodes,String lotNo){

    }
    
@Cacheable({"cache1", "cache2"})//Cache是发生在cache1和cache2上的
   public User find(Integer id) {
      returnnull;

   }
1.2 key属性

key属性是用来指定缓存方法返回结果对应的key的。该属性支持SpringEL表达式。当没有指定key时,将使用默认策略生成key。

1.2.1 自定义策略

自定义策略是指我们可以通过SpringEL表达式来指定key。EL表达式可以使用方法参数及他们对应的属性,使用方法参数时,可以直接使用“#参数名”或者“#p参数index”,如下所示:

第一种:
 @Cacheable(value = "getConfCustomer",key="#confCustomerCodes",unless="#result == null")
    public ConfCustomerInfoVo getConfCustomer(String confCustomerCodes){
        
    }
    
第二种:
@Cacheable(value = "getConfCustomer",key="#p0",unless="#result == null")
    public ConfCustomerInfoVo getConfCustomer(String confCustomerCodes){
        
    }
 
第三种:当参数是一个对象时
@Cacheable(value="users", key="#user.id")
   public User find(User user) {
      returnnull;
   }
@Cacheable(value="users", key="#p0.id")
   public User find(User user) {
      returnnull;
   }

除了可以使用上述方法作为key之外,Spring还提供了一个root对象可以用来生成key。使用方式如下:

属性名称描述示例
methodName当前方法名#root.methodName
method当前方法#root.method.name
target当前被调用的对象#root.target
targetClass当前被调用的对象的class#root.targetClass
args当前方法参数组成的数组#root.args[0]
caches当前被调用的方法使用的Cache#root.caches[0].name
  • #root也可以省略,如下:
@Cacheable(value={"users", "xxx"}, key="caches[1].name")
   public User find(User user) {
      returnnull;
   }
1.2.2 默认策略

默认的key的生成策略是通过KeyGenerator生成的。规则如下:

  • 如果没有参数,则使用0作为key
  • 如果只有一个参数,则使用该参数作为key
  • 如果多个参数,就是用参数的hashcode作为key
1.3 condition属性

有时候可能不需要缓存所有的返回结果,这就要用到condition。

condition默认为空,表示会缓存所有的返回结果。其值是通过SpringEL表达式指定的,当表达式为true时进行缓存,为false时不进行缓存,每次调用该方法都会执行一次condition表达式。如下示例表示只有当user的id为偶数时才会进行缓存。

 @Cacheable(value={"users"}, key="#user.id", condition="#user.id%2==0")
   public User find(User user) {
      System.out.println("find user by user " + user);
      return user;
   }
1.4 unless属性

unless也是通过SpringEL表达式指定的,表达式返回值符合条件的排除掉,只缓存不符合条件的。

  // 如果返回结果为null,则不进行缓存
  @Cacheable(value = "getConfCustomer",unless="#result == null")
    public ConfCustomerInfoVo getConfCustomer(String confCustomerCodes,String lotNo){
        ConfCustomerInfoVo confCustomerInfoVo = null;
        log.info("getConfCustomer-Redis调用");
        return confCustomerInfoVo;
    }
    
    // 如果缓存结果为false,则不进行缓存
    @Cacheable(value = "fruit", key = "#param", unless = "!#result")
	public boolean isApple(String param) {
		LatencyService.sleepAWhile(3);
		if (param.equals("apple")) {
			return true;
		}
		else {
			return false;
		}
	}

二、@CachePut

使用@CachePut注解,该方法每次都会执行,会清除对应key的缓存然后再添加(或者更新缓存)
@CachePut和@Cacheable参数一样,@CachePut可以实现缓存的更新,使数据库和缓存保持一致
@Cacheable更适用于查询方法,@CachePut更适用于更新方法。
官方强烈不推荐将 @Cacheable 和 @CachePut 注解到同一个方法。

// 更新数据库和缓存
@Override
    @CachePut(value = "menuById", key = "#menu.id")
    public Menu ReviseById(Menu menu) {
        this.updateById(menu);
        return menu;
    }
    
// 读取缓存的时候,可以读取到最新的数据
@Override
    @Cacheable(value = {"menuById"}, key = "#id")
    public Menu findById(String id) {
        Menu menu = this.getById(id);
        if (menu != null){
            System.out.println("menu.name = " + menu.getName());
        }
        return menu;
    }

三、@CacheEvict

@CacheEvict是用来标注在需要清除缓存元素的方法或者类上。属性value、key、condition、allEntries 和 beforeInvocation。
其中value、key、condition和@Cacheable一样。

3.1 allEntries属性

allEntries是boolean类型,表示是否需要清除缓存中的所有元素。默认为false,表示不需要。当指定allEntries为true时,Spring cache将忽略指定的key,删除掉所有的缓存。有时候需要清除所有的缓存,这样做比一个一个删除有效率的多。

@CacheEvict(value="users", allEntries=true)

   public void delete(Integer id) {

      System.out.println("delete user by id: " + id);

   }
3.2 beforeInvocation属性

清除操作默认是在方法执行成功之后触发的,即方法如果抛出异常未能成功返回则不会触发清除操作。使用beforeInvocation可以改变触发清除操作的时间,当我们指定该属性为true时,Spring会在调用该方法之前清除缓存中的指定元素。

 @CacheEvict(value="users", beforeInvocation=true)

   public void delete(Integer id) {

      System.out.println("delete user by id: " + id);

   }

四、@Cacheable不起作用的场合

1、配置文件中启用缓存:spring.cache.type=redis
2、缓存的对象必须实现Serializable

  public class ConfCustomerInfoVo extends BaseVo implements Serializable {
    }

3、.SpringBootApplication中要加@EnableCaching注解

@SpringBootApplication
@EnableDiscoveryClient
@EnableSwagger2
@EnableCaching
@EnableFeignClients(basePackages = {"com.newretail"})
@ComponentScan(basePackages = {"com.newretail"})
public class Application {
	public static void main(String[] args) {
		SpringApplication.run(Application.class, args);
	}
}

4、4.@Cacheable是基于Spring AOP代理类,内部方法调用是不走代理的,@Cacheable是不起作用的

public void get(){
	this.getCacheValue("123");
}

@Cacheable(value="getCache")
public List getCacheValue(String id){
	return ....
}
  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Spring框架通过Spring Cache提供了一套强大的缓存体系,可以轻松地实现缓存数据,提高应用程序的性能。Spring框架提供了三个主要的注解来实现缓存@Cacheable@CachePut@CacheEvict@Cacheable注解用于将方法的结果缓存起来,以便在下次请求时,如果参数相同,则可以直接从缓存中获取结果,而不需要重新计算。该注解适用于如果计算结果比较耗时,或者需要从数据库或其他外部资源中提取数据的情况。 @CachePut注解用于更新缓存中的数据。它与@Cacheable注解类似,但不同的是,它总是更新缓存数据,而不管缓存中是否已经存在该key的值。所以,可以使用这个注解来更新缓存中的数据。 @CacheEvict注解用于从缓存中删除数据。它在需要删除缓存数据的情况下使用。它可以删除指定的key对应的缓存,也可以清空所有缓存数据。 这三个注解都有一个可选参数Named:如果指定了该参数,则缓存将使用指定的名称使用。如果未指定,则使用默认的名称。可以使用不同名称的缓存来存储不同类型的数据,并使用不同的缓存策略来控制它们的存储方式。 除了Spring自带的缓存提供者之外,还可以使用其他的缓存提供者,如Ehcache、Redis、Memcached等等。在使用缓存时,需要注意的是,不同的缓存提供者之间可能会有不同的限制和性能差异。因此,必须根据实际情况选择最适合的缓存提供者和缓存策略,以获取最好的性能和可靠性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值