博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
8 -- 深入使用Spring -- 5...2 使用@Cacheable执行缓存
阅读量:6337 次
发布时间:2019-06-22

本文共 8182 字,大约阅读时间需要 27 分钟。

      8.5.2 使用@Cacheable执行缓存

        @Cacheable可用于修饰类或修饰方法,当使用@Cacheable修饰类时,用于告诉Spring在类级别上进行缓存 ------ 程序调用该类的实例的任何方法时都需要缓存,而且共享同一个缓存区;当使用@Cacheable修饰方法时,用于告诉Spring在方法级别上进行缓存 ------ 只有当程序调用该方法时才需要缓存。

        1. 类级别的缓存

          当使用@Cacheable修饰类时,就可控制Spring在类级别进行缓存,这样程序调用类的任意方法时,只要传入的参数相同,Spring就会使用缓存。

          Component : UserServiceImpl

package edu.pri.lime._8_5_2.classrank.impl;import org.springframework.cache.annotation.Cacheable;import org.springframework.stereotype.Service;import edu.pri.lime._8_5_2.classrank.UserService;import edu.pri.lime._8_5_2.classrank.bean.User;@Service(value="userService")@Cacheable(value = "users")public class UserServiceImpl implements UserService{    @Override    public User getUserByNameAndAge(String name, int age) {        System.out.println("---正在执行getUserByNameAndAge()查询方法---");        return new User(name,age);    }    @Override    public User getAnotherUser(String name, int age) {        System.out.println("---正在执行findAnotherUser()查询方法---");        return new User(name,age);    }}

          app_8_5_2_ehcache.xml:不成功,请使用SimpleCacheManager作为缓存管理器

          Class : SpringTest

package edu.pri.lime._8_5_2.classrank.impl;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import edu.pri.lime._8_5_2.classrank.UserService;import edu.pri.lime._8_5_2.classrank.bean.User;public class SpringTest {    public static void main(String[] args) {        ApplicationContext ctx = new ClassPathXmlApplicationContext("app_8_5_2_classrank.xml");        UserService userService = (UserService) ctx.getBean("userService");        User userA = userService.getUserByNameAndAge("lime", 24);        User userB = userService.getAnotherUser("lime", 24);        System.out.println(userA == userB);    }}

          Console : 

---正在执行getUserByNameAndAge()查询方法---true

          @Cacheable(value="users")指定UserServiceImple进行类级别的缓存,这样程序调用该类的任意方法时,只要传入的参数相同,Spring就会使用缓存,即时方法的返回值并不真正的同一个对象。

          此处所指的缓存的意义是:当程序第一次调用该类的实例的某个方法时,Spring缓存机制会将该方法返回的数据放入指定缓存区 ------ 就是@Cacheable注解的value属性所指定的缓存区(此处指定将数据放入users缓存区,正是缓存管理器配置的users缓存区)。以后程序调用该类的实例的任何方法时,只要出入的参数相同,Spring将不会真正执行该方法,而是直接利用缓存区中的数据。

          类级别的缓存默认以所有方法参数作为key来缓存方法返回的数据 ------ 同一类不管调用哪个方法,只要调用方法时传入的参数相同,Spring都会直接利用缓存区中的数据。

          使用@Cacheable时可指定如下属性:

            ⊙ value : 必需属性。该属性可指定多个缓存区的名字,用于指定将方法返回值放入指定的缓存区内。

            ⊙ key : 通过SpEL表达式显式指定缓存的key。多个参数组合的key 用#name + #age + ...

            ⊙ condition : 该属性指定一个返回boolean值的SpEL表达式,只有当该表达式返回true时,Spring才会缓存方法返回值。

            ⊙ unless : 该属性指定一个返回boolean值的SpEL表达式,当该表达式返回true时,Spring就不缓存方法返回值。

          提示:

            与@Cacheable注解功能类似的还有一个@CachePut注解,@CachePut注解同样会让Spring将方法返回值放入缓存区。与@Cacheable不同的是,@CachePut修饰的方法不会读取缓存区中的数据 ------ 这意味着不管缓存区是否已有数据,@CachePut总会告诉Spring要重新执行这些方法,并再次将方法返回值放入缓存区。

          修改UserServiceImpl : @Cacheable(value = “users” , key = “#name”) 显式指定以name参数作为缓存的key,这样只要调用的方法具有相同的name参数,Spring缓存机制就会生效。

package edu.pri.lime._8_5_2.classrank.service.cacheablekey.main;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import edu.pri.lime._8_5_2.classrank.bean.User;import edu.pri.lime._8_5_2.classrank.service.cacheable.UserService;public class SpringTest {    public static void main(String[] args) {        ApplicationContext ctx = new ClassPathXmlApplicationContext("app_8_5_2_classrankkey.xml");        UserService userService = (UserService) ctx.getBean("userService");        User userA = userService.getUserByNameAndAge("lime", 22);        User userB = userService.getAnotherUser("lime", 24);        System.out.println(userA == userB);            }}

            Console : 

---正在执行getUserByNameAndAge()查询方法---true

          使用@Cacheable注解显式指定key = “#name” ,这就意味着缓存使用name参数作为缓存的key。

          condition属性与unless属性的功能基本相似,但规则恰好相反:当condition指定的条件为true时,Spring缓存机制才会执行缓存;当unless指定的条件为true时,Spring缓存机制就不执行缓存。

            Class : UserServiceImpl

package edu.pri.lime._8_5_2.classrank.service.cacheablecondition.impl;import org.springframework.cache.annotation.Cacheable;import org.springframework.stereotype.Service;import edu.pri.lime._8_5_2.classrank.bean.User;import edu.pri.lime._8_5_2.classrank.service.cacheablecondition.UserService;@Service("userService")@Cacheable(value="users" ,condition="#age<100")public class UserServiceImpl implements UserService{    @Override    public User getUserByNameAndAge(String name, int age) {        System.out.println("---正在执行getUserByNameAndAge()查询方法---");        return new User(name,age);    }    @Override    public User getAnotherUser(String name, int age) {        System.out.println("---正在执行getAnotherUser()查询方法---");        return new User("oracle",25);    }}

            XML : 

            Console : 

---正在执行getUserByNameAndAge()查询方法------正在执行getAnotherUser()查询方法---false---正在执行getUserByNameAndAge()查询方法------正在执行getAnotherUser()查询方法---false---正在执行getUserByNameAndAge()查询方法------正在执行getAnotherUser()查询方法---false

            疑惑 : 跟想象中的不一样啊! 说好的condition表达式呢?

            使用@Cacheable修饰方法时,可控制Spring在方法级别进行缓存,这样当程序调用该方法时,只要传入的参数相同,Spring就会使用缓存。

        2.方法级别的缓存

          Class : UserServiceImpl

package edu.pri.lime._8_5_2.functionrank.service.impl;import org.springframework.cache.annotation.Cacheable;import org.springframework.stereotype.Service;import edu.pri.lime._8_5_2.functionrank.bean.User;import edu.pri.lime._8_5_2.functionrank.service.UserService;@Service("userService")public class UserServiceImpl implements UserService{    @Override    @Cacheable(value="userA")    public User getUserByNameAndAge(String name, int age) {        System.out.println("---正在执行getUserByNameAndAge()查询方法---");        return new User(name,age);    }    @Override    @Cacheable(value="userB")    public User getAnotherUser(String name, int age) {        System.out.println("---正在执行findAnotherUser()查询方法---");        return new User("oracle",25);    }}

          XML : app_8_5_2_functionrankvalue.xml

          Class : SpringTest

package edu.pri.lime._8_5_2.functionrank;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import edu.pri.lime._8_5_2.functionrank.bean.User;import edu.pri.lime._8_5_2.functionrank.service.UserService;public class SpringTest {    public static void main(String[] args) {        ApplicationContext ctx = new ClassPathXmlApplicationContext("app_8_5_2_functionrankvalue.xml");        UserService userService = ctx.getBean("userService",UserService.class);        User userA = userService.getUserByNameAndAge("lime", 24);        User userB = userService.getAnotherUser("lime", 24);        System.out.println(userA == userB);        User userC = userService.getUserByNameAndAge("lime", 24);        User userD = userService.getAnotherUser("lime", 24);        System.out.println(userA == userC);            }}

          Console : 

---正在执行getUserByNameAndAge()查询方法------正在执行findAnotherUser()查询方法---falsetrue

          方法级别的缓存中,方法之间使用不同的缓存区,因此它们不能共享缓存。

啦啦啦

啦啦啦

啦啦啦

啦啦啦

转载地址:http://xexoa.baihongyu.com/

你可能感兴趣的文章
【每天一个Linux命令】12. Linux中which命令的用法
查看>>
软件接口数据一致性机制
查看>>
微服务架构介绍和RPC框架对比
查看>>
Debian下使用OpenLDAP 管理端
查看>>
泛型排序器TComparer
查看>>
9个offer,12家公司,35场面试,从微软到谷歌,应届计算机毕业生的2012求职之路...
查看>>
创建符合标准的、有语意的HTML页面——ASP.NET 2.0 CSS Friendly Control Adapters 1.0发布...
查看>>
Adobe驳斥Flash过度耗电论 称HTML5更耗电
查看>>
No!No!No! It's not fashion!
查看>>
艰困之道中学到的经验教训
查看>>
互联网生态建设落地五大挑战——保险科技生态建设 ...
查看>>
进行短视频app开发工作时,可以加入它来保护青少年 ...
查看>>
25G DAC无源高速线缆和25G光模块之间的区别
查看>>
乐乐茶完成近2亿元Pre-A轮融资,祥峰投资领投
查看>>
clickhouse修改时区
查看>>
CSS_定位
查看>>
第二十四章:页面导航(六)
查看>>
百度、长沙加码自动驾驶,湖南阿波罗智行科技公司成立 ...
查看>>
10 个 Linux 中方便的 Bash 别名
查看>>
全新 DOCKER PALS 计划上线,带给您不一样的参会体验! ...
查看>>