Spring 3.1缓存和@Cacheable

缓存在软件领域已经存在很长时间了。 它们是那些真正有用的东西之一,一旦您开始使用它们,您会想知道如果没有它们,您是如何相处的,所以似乎让Spring的家伙们只是在版本中向Spring核心添加缓存实现有点奇怪。 3.1。 我猜想以前没有被视为优先事项,此外,在引入Java批注之前,缓存的困难之一是将缓存代码与业务代码耦合在一起,这通常会变得很混乱。

但是,Spring的家伙现在已经基于几个注释设计了一个易于使用的缓存系统:@Cacheable和@CacheEvict。

@Cacheable批注的想法是,您可以使用它来标记将存储在缓存中的方法返回值。 @Cacheable批注可以应用于方法级别或类型级别。 在方法级别应用时,将对带注释的方法的返回值进行缓存。 在类型级别应用时,将缓存每个方法的返回值。

下面的代码演示了如何在类型级别应用@Cacheable:

@Cacheable(value = "employee")
public class EmployeeDAO {

  public Person findEmployee(String firstName, String surname, int age) {

    return new Person(firstName, surname, age);
  }

  public Person findAnotherEmployee(String firstName, String surname, int age) {

    return new Person(firstName, surname, age);
  }
}

Cacheable批注采用三个参数:value(必填)以及key和condition。 其中第一个(值)用于指定存储a方法的返回值的一个或多个缓存的名称。

@Cacheable(value = "employee")
  public Person findEmployee(String firstName, String surname, int age) {

    return new Person(firstName, surname, age);
  }

上面的代码确保新的Person对象存储在“员工”缓存中。

缓存中存储的任何数据都需要一个密钥来快速检索。 默认情况下,Spring使用注释方法的签名创建缓存密钥,如上面的代码所示。 您可以使用@Cacheable的第二个参数:key覆盖它。 要定义自定义键,请使用SpEL表达式。

@Cacheable(value = "employee", key = "#surname")
  public Person findEmployeeBySurname(String firstName, String surname, int age) {

    return new Person(firstName, surname, age);
  }

在findEmployeeBySurname(…)代码中,“#surname”字符串是SpEL表达式,表示“使用findEmployeeBySurname(…)方法的surname参数创建并创建密钥”。

最后的@Cacheable参数是可选的条件参数。 同样,这引用了SpEL表达式,但是这次它指定了一个条件,该条件用于确定是否将方法的返回值添加到缓存中。

@Cacheable(value = "employee", condition = "#age < 25")
  public Person findEmployeeByAge(String firstName, String surname, int age) {

    return new Person(firstName, surname, age);
  }

在上面的代码中,我应用了可笑的业务规则,即如果雇员不到25岁,则仅缓存Person对象。

快速演示了如何应用某些缓存后,接下来要做的就是看一看所有含义。

@Test
  public void testCache() {

    Person employee1 = instance.findEmployee("John", "Smith", 22);
    Person employee2 = instance.findEmployee("John", "Smith", 22);

    assertEquals(employee1, employee2);
  }

上面的测试演示了最简单的缓存。 第一次调用findEmployee(...),结果尚未缓存,因此将调用我的代码,Spring将其返回值存储在缓存中。 在对findEmployee(...)的第二次调用中,未调用我的代码,Spring返回了缓存的值; 因此,局部变量employee1引用了与employee2相同的对象引用,这意味着以下情况成立:

assertEquals(employee1, employee2);

但是,事情并非总是那么清晰。 记住,在findEmployeeBySurname中,我已经修改了缓存密钥,以便使用surname参数创建密钥,而在创建自己的密钥算法时要注意的事情是确保任何密钥都引用唯一的对象。

@Test
  public void testCacheOnSurnameAsKey() {

    Person employee1 = instance.findEmployeeBySurname("John", "Smith", 22);
    Person employee2 = instance.findEmployeeBySurname("Jack", "Smith", 55);

    assertEquals(employee1, employee2);
  }

上面的代码找到了两个Person实例,这些实例显然指向不同的员工; 但是,由于我只缓存姓氏,因此Spring将返回对我第一次调用findEmployeeBySurname(…)时创建的对象的引用。 对于Spring来说这不是问题,但是由于我的缓存键定义不佳。

当引用由将条件应用于@Cachable注释的方法创建的对象时,必须采取类似的措施。 在我的示例代码中,我应用了仅缓存员工年龄在25岁以下的Person实例的任意条件。

@Test
  public void testCacheWithAgeAsCondition() {

    Person employee1 = instance.findEmployeeByAge("John", "Smith", 22);
    Person employee2 = instance.findEmployeeByAge("John", "Smith", 22);

    assertEquals(employee1, employee2);
  }

在上面的代码中,对employee1和employee2的引用是相等的,因为在第二次调用findEmployeeByAge(...)时,Spring返回其缓存的实例。

@Test
  public void testCacheWithAgeAsCondition2() {

    Person employee1 = instance.findEmployeeByAge("John", "Smith", 30);
    Person employee2 = instance.findEmployeeByAge("John", "Smith", 30);

    assertFalse(employee1 == employee2);
  }

同样,在上面的单元测试代码中,对employee1和employee2的引用引用了不同的对象,在这种情况下,John Smith已超过25岁。

这仅涉及@Cacheable,但是@CacheEvict和清除缓存中的项目呢? 另外,还有一个问题,就是在您的Spring配置中添加缓存并选择合适的缓存实现。 但是,稍后会有更多……。

参考:来自Captain Debug's Blog博客的JCG合作伙伴 Roger Hughes的Spring 3.1 Caching和@Cacheable


翻译自: https://www.javacodegeeks.com/2012/09/spring-31-caching-and-cacheable.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值