SpringBoot中@Cache同类调用不生效切换AspectJ

简述问题

我们在 SpringBoot 中使用 @Cacheable 时,在某个方法调用同类中的另一个方法,则另一个方法的缓存不会生效。

比如:

1
2
3
4
5
6
7
8
9
10
11
12
@Override
@Cacheable(value = "allUsersCache", key = "#id")
public String init(String id) {
this.init2("self_key");
return "init_";
}

@Override
@Cacheable(value = "userCache", key = "#id")
public String init2(String id) {
return "init2_";
}

我们如果查看结果只能看到 init参与了缓存,而init2没有参与缓存。

原因

SpringBoot@EnableCaching 默认使用的是 PROXY,也就是Spring AOP,那么在同一个类中,方法间的调用并不会出发proxy

如何解决

1、self 方式解决

这种 self 方式是最直接最简单的,比如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@Slf4j
@Service
public class CustomCacheService implements ICustomCacheService {
/**
* 1. Self-autowired reference to proxified bean of this class.
*/
@Resource
private ICustomCacheService self;

@Override
@Cacheable(value = "allUsersCache", key = "#id")
public String init(String id) {
// 2. call cached method using self-bean
self.init2("self_key");
return "init_";
}

@Override
@Cacheable(value = "userCache", key = "#id")
public String init2(String id) {
return "init2_";
}
}

下面是 AdviceMode源代码,枚举说明也简单直接。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
* Enumeration used to determine whether JDK proxy-based or
* AspectJ weaving-based advice should be applied.
*
* @author Chris Beams
* @since 3.1
* @see org.springframework.scheduling.annotation.EnableAsync#mode()
* @see org.springframework.scheduling.annotation.AsyncConfigurationSelector#selectImports
* @see org.springframework.transaction.annotation.EnableTransactionManagement#mode()
*/
public enum AdviceMode {

/**
* JDK proxy-based advice.
*/
PROXY,

/**
* AspectJ weaving-based advice.
*/
ASPECTJ
}

2、切换为AspectJ

SpringBoot@EnableCaching 默认使用的是 PROXY,我们可以直接切换为 AspectJ

比如:@EnableCaching(mode = AdviceMode.ASPECTJ)

Spring xml中可以配置

1
<cache:annotation-driven mode="aspectj"/>

推荐

SpringBoot整合Redis与Cache与实现
SpringBoot整合Redis及Redis简介和操作

本文地址: https://github.com/maxzhao-it/blog/post/6375/