本地 AOP 实现缓存

因为本地不能使用 spring-cache,我就是为了测试缓存能提升多大性能,而想出来的野路子。

CacheAspect

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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
package com.amoros.pumpkin.scorecard.infrastructure;

import com.amoros.cloud.core.AgentId;
import com.google.common.collect.Sets;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Pointcut;

import java.util.Arrays;
import java.util.HashMap;

/**
* 缓存切面
*
* @author 陶攀峰
* @date 2022-01-30 10:04
*/
// @Aspect
// @Component
@Slf4j
public class CacheAspect {

private static final HashMap<String, Object> CACHE = new HashMap<>(1 << 10);

@Pointcut("execution(* com.amoros.pumpkin.scorecard.gateway.*.*(..)))")
private void pointcut() {
}

@Around("pointcut()")
public Object aroud(ProceedingJoinPoint joinPoint) {
try {
// 前置
Object[] args = joinPoint.getArgs();
String methodName = joinPoint.getSignature().getName();
// Class<?> declaringType = joinPoint.getSignature().getDeclaringType();
// String declaringTypeName = joinPoint.getSignature().getDeclaringTypeName();

// String kind = joinPoint.getKind();

// SourceLocation sourceLocation = joinPoint.getSourceLocation();
// Class<?> withinType = joinPoint.getSourceLocation().getWithinType();
// String name1 = joinPoint.getSourceLocation().getWithinType().getName();
String sourceClassName = joinPoint.getSourceLocation().getWithinType().getSimpleName();

// MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
// String declaringTypeName1 = methodSignature.getDeclaringTypeName();
//
// Method method = methodSignature.getMethod();
// String methodName1 = method.getName();

String agentUid = AgentId.getAgentUid();
// if (StringUtils.isNotEmpty(agentUid)) {
if (StringUtils.isNotEmpty(agentUid) &&
!Sets.newHashSet("FeatureScoreStandGwImpl", "FeatureScGwImpl", "ScReportGwImpl").contains(sourceClassName)) {

// 走缓存
String cacheKey = agentUid + "_" + sourceClassName + "_" + methodName + "_" + Arrays.toString(args);
Object res = CACHE.computeIfAbsent(cacheKey, key -> joinPointProceed(joinPoint));
if ("CacheImpl".equals(sourceClassName)){
// log.info("CacheAspect.CACHE:{}", JSON.toJSONString(CACHE.keySet()));
CACHE.clear();
}
return res;
}

// 后置
return joinPointProceed(joinPoint);
} catch (Throwable t) {
// 异常
log.info("CacheAspect.aroud 执行异常", t);
throw new RuntimeException();
} finally {
// 最终
}
}

private Object joinPointProceed(ProceedingJoinPoint joinPoint) {
try {
return joinPoint.proceed(joinPoint.getArgs());
} catch (Throwable t) {
// 异常
log.info("CacheAspect.joinPointProceed 执行异常", t);
throw new RuntimeException();
}
}


}

CacheImpl

定义这个是为了测试完毕后,清理缓存。
是为了方便我调整 db 的参数后,再重新进行测试。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.amoros.pumpkin.scorecard.gateway.impl;

import org.springframework.stereotype.Service;

/**
* 描述
*
* @author 陶攀峰
* @date 2022-01-30 12:55
*/
@Service
public class CacheImpl {

public void clear(){
}
}

clear使用

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
/**
* 计分卡创建
*
* @param jobHandlerName job handler 名称
* @param jsonParam 定时任务 入参
* @return 任务是否执行成功
*/
private ReturnT<String> scCreate(String jobHandlerName, String jsonParam) {
// [0] 创建什么类型计分卡
ScTypeEnum scTypeEnum = getScTypeEnum(jobHandlerName);

try {

// [1] 解析入参
ScCreateCmd scCreateCmd = JSON.parseObject(jsonParam, ScCreateCmd.class);

// [2] 校验参数
checkParam(scCreateCmd, scTypeEnum);

// [3] 执行计分卡创建
methodRouter(scCreateCmd, jobHandlerName);

return ReturnT.SUCCESS;
} catch (Exception e) {
XxlJobLoggerUtils.error("计分卡生成出错", e);
return ReturnT.FAIL;
} finally {
ScoreCardContextHolder.remove();
cacheImpl.clear();
}

}
@Autowired
private CacheImpl cacheImpl;