Spring之路(47)–Spring编程式缓存管理实例
2020/2/20 8:09:34
本文主要是介绍Spring之路(47)–Spring编程式缓存管理实例,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
编程式缓存管理
还记得之前讲过的编程式事务管理与声明式事务管理吗,编程式管理说白了就是自己手工编程去管理。
因为手工编程式的管理方式,更加基础,更加容易理解,所以我们从编程式缓存管理说起。
实现方式
其实思路非常简单,缓存是针对方法的,我们将对方法的请求加入缓存中,如果再次对该方法发起同样请求(同一方法且参数相同),则不执行该方法,直接取出缓存即可。
项目准备
为了可以使用AOP,再进行本文内容时,除了前面一直提到Spring的jar包,还需要引入aspectjweaver-1.8.1.jar
,这个包是Spring AOP所需要的。
不使用缓存的情况
1、定义数据DO、数据访问DAO、数据服务Service
首先定义BlogDao用来访问数据库,根据博客表的id获取博客信息
@Repository // 注册为bean public class BlogDao { @Autowired // 自动注入 private NamedParameterJdbcTemplate namedParameterJdbcTemplate; /** * 查询数据库 */ public BlogDo getById(Long id) { System.out.println("执行getById:" + id); Map<String, Object> map = new HashMap<>(); map.put("id", id); return namedParameterJdbcTemplate.queryForObject("select * from blog where id=:id", map, new RowMapper<BlogDo>() { @Override public BlogDo mapRow(ResultSet rs, int rowNum) throws SQLException { BlogDo blog = new BlogDo(); blog.setAuthor(rs.getString("author")); blog.setContent(rs.getString("content")); blog.setId(rs.getLong("id")); blog.setTitle(rs.getString("title")); return blog; } }); } }
然后定义BlogService提供操作封装。
@Service//注册bean public class BlogService { @Autowired//自动注入 private BlogDao blogDao; public BlogDo getById(Long id) { return blogDao.getById(id); } }
数据对象BlogDo就不用多说了:
public class BlogDo { private Long id; private String title; private String author; private String content; //省略get set }
2、编写Spring配置类SpringConfig
在配置类中开启bean扫描,以便将BlogService和BlogDao注册bean,同时注册数据源bean和namedParameterJdbcTemplate用于操作数据库。
@Configuration // 配置类 @ComponentScan(basePackages = { "org.maoge.cachedemo.mannual" }) // 扫描包以便发现注解配置的bean public class SpringConfig { // 配置数据源 @Bean public DataSource dataSource() { DruidDataSource dataSource = new DruidDataSource(); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/myblog?useUnicode=true&characterEncoding=utf-8"); dataSource.setUsername("root"); dataSource.setPassword("Easy@0122"); return dataSource; } // 配置namedParameterJdbcTemplate组件 @Bean public NamedParameterJdbcTemplate namedParameterJdbcTemplate() { NamedParameterJdbcTemplate template = new NamedParameterJdbcTemplate(dataSource());// 注入dataSource return template; } }
3、测试
从容器中取出BlogService,然后调用其getList方法进行测试:
public class Main { public static void main(String[] args) throws SQLException { // 获取容器 AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class); // 获取blogService组件 BlogService blogService = context.getBean("blogService", BlogService.class); // 测试获取列表 for(int i=0;i<10;i++) { blogService.getById(1L); } } }
输出结果如下,可见真实的调用了BlogDao的getById方法10次。
执行getById:1 执行getById:1 执行getById:1 执行getById:1 执行getById:1 执行getById:1 执行getById:1 执行getById:1 执行getById:1 执行getById:1
编程式管理管理的情况
1、修改配置类启用缓存并注册缓存管理器
首先通过@EnableCaching
启用缓存功能。然后注册缓存管理器bean,我们通过缓存管理器对缓存进行管理。
@Configuration // 配置类 @ComponentScan(basePackages = { "org.maoge.cachedemo.mannual" }) // 扫描包以便发现注解配置的bean @EnableCaching // 启用缓存 public class SpringConfig { // 配置数据源 @Bean public DataSource dataSource() { DruidDataSource dataSource = new DruidDataSource(); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/myblog?useUnicode=true&characterEncoding=utf-8"); dataSource.setUsername("root"); dataSource.setPassword("Easy@0122"); return dataSource; } // 配置namedParameterJdbcTemplate组件 @Bean public NamedParameterJdbcTemplate namedParameterJdbcTemplate() { NamedParameterJdbcTemplate template = new NamedParameterJdbcTemplate(dataSource());// 注入dataSource return template; } // 配置缓存管理器 @Bean public CacheManager cacheManager() { SimpleCacheManager cacheManager = new SimpleCacheManager(); //缓存管理器中有很多缓存caches,其中一个名字为blogs cacheManager.setCaches(Arrays.asList(new ConcurrentMapCache("blogs"))); return cacheManager; } }
务必注意,我们像缓存管理其中添加了一个名字为blogs
的ConcurrentMapCache类型对象,该对象是个字典形式的缓存,也就是说在blogs这个缓存,参数只要确定了,其缓存的值就确定了。
2、调用BlogService.getById时添加缓存逻辑
不存在缓存时,将结果放入缓存;存在缓存,则不再执行具体方法,直接返回缓存。
@Service//注册bean public class BlogService { @Autowired//自动注入 private BlogDao blogDao; @Autowired//自欧东注入 private CacheManager cacheManager; public BlogDo getById(Long id) { //取出名字为blogs的缓存 Cache cache=cacheManager.getCache("blogs"); //判断针对参数id的值,是否有缓存存在 if(cache.get(id)==null) {//不存在,则查询数据库,并将结果纳入缓存 BlogDo result=blogDao.getById(id); cache.put(id, result); return result; }else {//存在则直接返回缓存即可 return (BlogDo)cache.get(id).get();//这个取值方式稍微有点绕 } } }
看明白了吗,首先缓存管理器可能要管理很多个缓存,比如用户缓存、角色缓存、机构信息缓存等等,所以需要先定义有几个缓存Cache,此处只有一个就是cacheManager.setCaches(Arrays.asList(new ConcurrentMapCache("blogs")));
。
然后,一个缓存其实就是一个线程安全的键值对,将方法的参数作为键,方法的返回值作为值,存储起来。当新的请求到达时,如果请求参数都相同,则不必再去查数据库了,直接返回缓存就行,反正请求的是一个东西。
3、测试
同样代码进行测试
public class Main { public static void main(String[] args) throws SQLException { // 获取容器 AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class); // 获取blogService组件 BlogService blogService = context.getBean("blogService", BlogService.class); // 测试获取列表 for(int i=0;i<10;i++) { blogService.getById(1L); } } }
结果输出如下:
执行getById:1
这意味着什么,我们成功的使用了缓存,对数据库的访问得到了极大的减少。如果使用得当的话,系统性能会得到一个跃进!
如果你不放心的话,可以下个断点,看看是不是返回的值是正确的。
上面的缓存方式太复杂了,你应该看到了模板代码的痕迹,凡是重复必能抽象优化,这种模板代码用AOP解决,SOEASY啊。
然后缓存其实还有不少注意点,我将在接下来给大家详细演示和解释。
这篇关于Spring之路(47)–Spring编程式缓存管理实例的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-05-13TiDB + ES:转转业财系统亿级数据存储优化实践
- 2024-05-09“2024鸿蒙零基础快速实战-仿抖音App开发(ArkTS版)”实战课程已上线
- 2024-05-09聊聊如何通过arthas-tunnel-server来远程管理所有需要arthas监控的应用
- 2024-05-09log4j2这么配就对了
- 2024-05-09nginx修改Content-Type
- 2024-05-09Redis多数据源,看这篇就够了
- 2024-05-09Google Chrome驱动程序 124.0.6367.62(正式版本)去哪下载?
- 2024-05-09有没有大佬知道这种数据应该怎么抓取呀?
- 2024-05-09这种运行结果里的10.100000001,怎么能最快改成10.1?
- 2024-05-09企业src漏洞挖掘-有意思的命令执行