好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

springboot 缓存@EnableCaching实例

springboot 缓存@EnableCaching

很多时候系统的瓶颈都在一些比较复杂的IO操作,例如读取数据库,如果一些比较稳定的数据,一般的解决方案就是用缓存。spring boot提供了比较简单的缓存方案。只要使用 @EnableCaching即可完成简单的缓存功能。

缓存的实现有多种实现,ConcurentHashMapCache , GuavaCache, EnCacheCache等多种实现,spring boot 有默认的实现。本文不深入源码解读,首先用起来。

此处我们模拟要缓存的User

?

1

2

3

4

5

class User {

  private Long id;

  private String name;

// setter getter

}

然后我们业务对象:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

import javax.annotation.PostConstruct;

import org.springframework.cache.annotation.CacheEvict;

import org.springframework.cache.annotation.CachePut;

import org.springframework.cache.annotation.Cacheable;

import org.springframework.cache.annotation.EnableCaching;

import org.springframework.stereotype.Component;

/**

  * @author micro

  * @date 2017年8月2日

  * @description :

  */

@Component

@EnableCaching

public class UserDao {

  private Map<Long, User> userMap;

  @PostConstruct

  public void init() {

   //模拟数据库

   userMap = new HashMap<Long, User>();

   userMap.put(1L, new User(1L, "micro1" ));

   userMap.put(2L, new User(2L, "micro2" ));

  }

 

  @Cacheable ( "user" )  // 注解key属性可以执行缓存对象user(可以理解为一个map)的key

  public User getUser(Long userId) {

   System.out.println( "查询数据库:userId ->" + userId);

   return userMap.get(userId);

  }

 

  @Cacheable (value = "nameCache" , key = "#name" )

  public User getUserByName(Long userId, String name) {

   System.out.println( "查询数据库:userId ->" + userId);

   return userMap.get(userId);

  }

 

  @Cacheable ( "nameCache" )

  public User getUserByName(String name) {

   System.out.println( "查询数据库:userName : " + name);

   for (Long k : userMap.keySet()) {

    if (userMap.get(k).equals(name)) {

     return userMap.get(k);

    }

   }

   return null ;

  }

 

  @CachePut ( "user" ) // 与Cacheable区别就是Cacheable先看缓存如果有,直接缓存换回,CachePut则是每次都会调用并且把返回值放到缓存

  public User getUser2(Long userId) {

   System.out.println( "查询数据库:userId : " + userId);

   return userMap.get(userId);

  }

 

  @CacheEvict ( "user" )

  public void removeFromCache(Long userId) {

   return ;

  }

}

然后我们编写启动类:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

@SpringBootApplication

public class CacheTest implements CommandLineRunner {

  @Autowired

  private UserDao userDao;

  public static void main(String[] args) {

   new SpringApplication(CacheTest. class ).run(args);

  }

  @Override

  public void run(String... args) throws Exception {

   System.out.println( "第一次查询" );

   System.out.println(userDao.getUser(1L));

   System.out.println( "第二次查询" );

   System.out.println(userDao.getUser(1L));

   userDao.removeFromCache(1L); // 移除缓存

   System.out.println( "第三次查询" );

   userDao.getUser(1L); // 没有缓存了 

   System.out.println( "--------" );

   // 测试不同的key缓存

   userDao.getUserByName( "micro1" );

   userDao.getUserByName(1L, "micro1" ); // 指定了参数name 为key 此次读取缓存

  }

}

打印结果:

第一次查询
查询数据库:userId ->1
User@65da01f4
第二次查询
User@65da01f4
第三次查询
查询数据库:userId ->1
--------
查询数据库:userName : micro1

Spring @EnableCaching的工作原理

1、开发人员使用注解@EnableCaching

2、注解@EnableCaching导入CachingConfigurationSelector

3、CachingConfigurationSelector根据注解@EnableCaching 属性AdviceMode mode决定引入哪些配置类

PROXY : AutoProxyRegistrar,ProxyCachingConfiguration; ASPECTJ : AspectJCachingConfiguration;

本文以mode=PROXY为例;

4、CachingConfigurationSelector导入AutoProxyRegistrar会确保容器中存在一个自动代理创建器(APC);

用于确保目标bean需要被代理时有可用的代理创建器

5、ProxyCachingConfiguration向容器定义如下基础设施bean

名称为org.springframework.cache.config.internalCacheAdvisor类型为BeanFactoryCacheOperationSourceAdvisor的bean 名称为cacheOperationSource类型为CacheOperationSource的bean

用于获取方法调用时最终应用的Spring Cache注解的元数据

名称为cacheInterceptor类型为CacheInterceptor的bean

一个MethodInterceptor,包裹在目标bean外面用于操作Cache的AOP Advice。

6、AutoProxyRegistrar在容器启动阶段对每个bean创建进行处理,如果该bean中有方法应用了Spring Cache注解,为其创建相应的代理对象,包裹上面定义的BeanFactoryCacheOperationSourceAdvisor bean;

7、使用了Spring Cache注解的bean方法被调用,其实调用首先发生在代理对象上,先到达cacheInterceptor,然后才是目标bean方法的调用;

cacheInterceptor既处理调用前缓存操作,也处理调用返回时缓存操作

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。

原文链接:https://blog.csdn.net/micro_hz/article/details/76599632

查看更多关于springboot 缓存@EnableCaching实例的详细内容...

  阅读:22次