@Cacheable注解在spring3中的使用-实现缓存

在软件开发中使用缓存已经有一个非常久的历史了。缓存是一种很好的设计思想,一旦你用了他,你将会发现他确实很有用。Spring3.1版本的核心对缓存做了实现。在Java推出Annotation特性之前,实现缓存的一个难点在于它与业务逻辑代码的耦合性太强。

然而,Spring3.1中使用@Cacheable 和@CacheEvict实现缓存在某种程度上解决了这个问题,基本思想是在方法加上@Cacheable注解,这个方法的返回值将具有缓存特性。

@Cacheable注解可以用在方法或者类级别。当他应用于方法级别的时候,就是如上所说的缓存返回值了。当应用在类级别的时候,这个类的所有方法的返回值都将被缓存。

?


1

2

3

4

5

6

7

8

9

10

11

12

13

@Cacheable(value
"employee")

publicclass

EmployeeDAO {

  publicPerson
findEmployee(String firstName, String surname, 
intage)
{

    returnnew

Person(firstName, surname, age);

  }

  publicPerson
findAnotherEmployee(String firstName, String surname, 
intage)
{

    returnnew

Person(firstName, surname, age);

  }

}

@Cacheable注解有三个参数,value是必须的,还有key和condition。第一个参数,也就是value指明了缓存将被存到什么地方。

?


1

2

3

4

5

@Cacheable(value
"employee")

 publicPerson
findEmployee(String firstName, String surname, 
intage)
{

   returnnew

Person(firstName, surname, age);

 }

任何存储在缓存中的数据为了高速访问都需要一个key。Spring默认使用被@Cacheable注解的方法的签名来作为key,当然你可以重写key,自定义key可以使用SpEL表达式。

?


1

2

3

4

<span
style=
"font-size:14px;">@Cacheable(value
"employee",
key = 
"#surname")</span>   publicPerson
findEmployeeBySurname(String firstName, String surname, 
intage)
{

    returnnew

Person(firstName, surname, age);

  }

在findEmployeeBySurname()的注解中"#surname"是一个SpEL表达式,他将使用findEmployeeBySurname()方法中的surname参数作为key。

@Cacheable的最后一个参数是condition(可选),同样的,也是引用一个SpEL表达式。但是这个参数将指明方法的返回结果是否被缓存。

?


1

2

3

4

5

@Cacheable(value
"employee",
condition = 
"#age
< 25"
)

 publicPerson
findEmployeeByAge(String firstName, String surname, 
intage)
{

   returnnew

Person(firstName, surname, age);

 }

上面的例子中,只有年龄小于25的时候才被缓存。

在快速看完了如何使用缓存后,我们接下来看看缓存带来的效果。

?


1

2

3

4

5

6

7

8

@Test

  publicvoid

testCache() {

    Person
employee1 = instance.findEmployee(
"John""Smith"33);

    Person
employee2 = instance.findEmployee(
"John""Smith"33);

    assertEquals(employee1,
employee2);

  }

上面的例子很简单,第一次调用findEmployee,findEmployee方法将被执行,Spring将他的返回值一个person对象存入缓存。第二次调用findEmployee的时候findEmployee将不被执行,Spring直接将缓存中的数据作为返回值返回。所以employee1
和employee2引用了同样的对象。

而下面的例子中,我们将年龄小于25作为缓存条件,就将得到不同的结果。

?


1

2

3

4

5

6

7

8

@Test

 publicvoid

testCacheWithAgeAsCondition() {

   Person
employee1 = instance.findEmployeeByAge(
"John""Smith"33);

   Person
employee2 = instance.findEmployeeByAge(
"John""Smith"33);

   assertEquals(employee1,
employee2);

 }

下面的例子我们在findEmployeeBySurname的方法的注解中自定义了key,我们使用了自定义的key生成方式,以确保不同的surname将会指向不同的人。看下面的程序:

?


1

2

3

4

5

6

7

8

@Test

 publicvoid

testCacheOnSurnameAsKey() {

   Person
employee1 = instance.findEmployeeBySurname(
"John""Smith"22);

   Person
employee2 = instance.findEmployeeBySurname(
"Jack""Smith"55);

   assertEquals(employee1,
employee2);

 }

我们想找到两个不同的人,但是两个人的surname是相同的,你将发现两次调用返回了相同的结果,这不是Spring的问题,而是我们的cache key的生成方式有问题。所以在我们定义key的时候要小心注意key的生成策略,避免造成这种问题。

最后总结一下流程,当执行到一个被@Cacheable注解的方法时,Spring首先检查condition条件是否满足,如果不满足,执行方法,返回;如果满足,在value所命名的缓存空间中查找使用key存储的对象,如果找到,将找到的结果返回,如果没有找到执行方法,将方法的返回值以key-对象的方式存入value缓存中,然后方法返回。

上文仅仅是@Cacheable的使用方法,但是我们怎么使用@CacheEvict注解来清除缓存呢?另外,还有一个问题,如何选择一个缓存的实现,并配置Spring的缓存呢?欲知后事如何,且听下回分解。

时间: 2024-10-15 08:24:57

@Cacheable注解在spring3中的使用-实现缓存的相关文章

Spring的Bean内部方法调用无法使用AOP切面(CacheAble注解失效)

今天在使用Spring cache的Cacheable注解的过程中遇见了一个Cacheable注解失效的问题,检查问题发生的原因是因为Spring的Cacheable注解是基于Spring AOP实现的,但是类内部方法互相调用时不会被Spring AOP拦截的,所以导致被调用方法的Cacheable注解失效,特此记录. 问题复现 @Service public class UserServiceImpl{ @Override public User detail(Long id) { // 校验

在Spring3中使用注解(@Scheduled)创建计划任务

Spring3中加强了注解的使用,其中计划任务也得到了增强,现在创建一个计划任务只需要两步就完成了: 创建一个Java类,添加一个无参无返回值的方法,在方法上用@Scheduled注解修饰一下: 在Spring配置文件中添加三个<task:**** />节点: 最后说明一下,第一步创建的Java类要成为Spring可管理的Bean,可以直接写在XML里,也可以@Component一下 计划任务类: /** * com.zywang.spring.task.SpringTaskDemo.java

Spring @Cacheable注解 &amp;&amp; 事务@Transactional 在同一个类中的方法调用不生效

@Cacheable 注解在对象内部调用不会生效 代码示例:ProductServiceImpl.java public List<ProductInfoVO> getProductList(CommonRequest<ProductInfoDTO> reqest) { // @Cacheable失效,不会走缓存的 return this.findProductInfoList(reqest); } @Cacheable(cacheNames = "productInfo

Spring3中的Formatter结合Velocity格式化输出实例

看本文之前,希望你对Spring3的Formatter机制有所了解,还不了解的可以猛戳这里. Spring3中对于格式化有两种级别,一种是针对类型级别的格式化,另一种是针对字段的格式化. 首先,针对类型级别的格式化也就是说,比如对于Date类型,我都采用一种格式化方案,那么可以用如下方式注册: conversionService.addFormatter(new Formatter<Date>() { @Override public String print(Date object, Loc

Spring MVC 中采用注解方式 Action中跳转到另一个Action的写法

Spring MVC 中采用注解方式 Action中跳转到另一个Action的写法 在Action中方法的返回值都是字符串行,一般情况是返回某个JSP,如: return "xx":意思是返回到某个JSP页面上 如果想在此Action中跳转到另一个Action中怎样做呢? return "redirect://.do?" 例如: @RequestMapping(params = "action=delete") public String del

注解在android中的使用

注解在android程序中的使用 何为注解: 在Java当中,注解又叫做"元数据",它为我们在源代码中添加信息提供了一种形式化的方法,让我们能在以后的某个时间方便的使用这些数据.更确切的说,注解在一定的程度上将数据与元代码进行了绑定,并不是将数据保存在外部文件中.当然,这里只介绍Android开发相关的技术,至于注解我会在Java学习总结篇中进行详细的研究和总结.那么,接下来我们一个实例来介绍注解在android开发中的巧妙应用. 实例描述: 在这里,我们使用注解替换掉android中

Springboot中使用自定义参数注解获取 token 中用户数据

使用自定义参数注解获取 token 中User数据 使用背景 在springboot项目开发中需要从token中获取用户信息时通常的方式要经历几个步骤 拦截器中截获token TokenUtil工具类解析token中的用户信息 把解析结果存入到成员变量中 controller中通过TokenUtil工具类提供的静态方法获取用户信息 下面是过程示例代码 /*--------1.拦截器中获取---------*/ String token =request.getHeader("token"

Spring Boot Ehcache使用@Cacheable同key不同value是否能被缓存?

[视频&交流平台] à SpringBoot网易云课堂视频 http://study.163.com/course/introduction.htm?courseId=1004329008 à Spring Boot交流平台 http://412887952-qq-com.iteye.com/blog/2321532 需求缘起: 有人咨询博主,如下问题:   上面的问题翻译下就是:使用@Cacheable同key不同value是否能被缓存? 对于这个问题,试一下就知道怎么回事了,好了,这篇博客就

关于这周工作中遇到的关于缓存问题的记录

序:本周在工作中遇到了一些麻烦,解决过程比较曲折和辛苦,特此记录,留作经验供以后参考 发现问题:周一上班的时候,运营打电话来说,我们上个月做的一个活动感觉数据不对,商家过来投诉了.结果我数据库一查,数据还真有问题!这次的活动采用的是页面上使用缓存系统显示活动数值(总金额),同时在后台记录详细的每条活动数据的办法.每次用户发生业务行为的时候都会在后台的缓存的总金额上增加,同时记录这次行为发生的金额数.结果我周一把数据库的记录加一起来一算,发现和页面上缓存的总金额竟然差了将近一半! 解决的过程: 1