需求
项目中共用了一个Redis,而项目中部分代码使用了JetCache的@Cached注解。所以需要给@Cached动态配置area属性值,用来区分dev和test环境。
问题
自定义注解的属性值需要常量值,即static final修饰,直接通过配置文件不可行。
解决方案
1、使用AOP切面拦截使用注解的方法,动态修改注解的属性值。切面1。
2、注解的底层一般也有一个AOP切面。切面2。
需要确保切面1在切面2之前执行 (使用@order(int)注解,值越小越先执行)。
示例代码
yml配置文件:
1 2
| testAop: actionValue: 测试-10101908-action
|
切面1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| @Component @Aspect @Slf4j @Order(1) public class MyAspect {
@Value("${testAop.actionValue}") private String actionValue;
@Before(value = "@annotation(webLogAnnotation)") public void aopTest(WebLogAnnotation webLogAnnotation) throws Throwable { InvocationHandler invocationHandler = Proxy.getInvocationHandler(webLogAnnotation); Field value = invocationHandler.getClass().getDeclaredField( "memberValues"); value.setAccessible(true); Map<String,Object> memberValues = (Map<String,Object>) value.get(invocationHandler); memberValues.put("action", actionValue); log.info("MyAspect.aopTest memberValues:{}",memberValues); } }
|
切面2:
1 2 3 4 5 6 7 8 9
| @Component @Aspect @Order(2) public class WebLogAspect{
@Around("@annotation(webLogAnnotation)") public Object logAround(ProceedingJoinPoint joinPoint, WebLogAnnotation webLogAnnotation) throws Throwable { }
|
controller:
1 2 3 4 5
| @PostMapping("/getList") @WebLogAnnotation(logType = "30010051",action = "通讯录-分页查询列表action",description = "'通讯录-分页查询列表desc'") public PageResponseMsg<AddressBookVo> getList(@RequestBody @Valid PageRequest<QueryAddressBookListReq> pageDto){ }
|
经测试,WebLogAspect中成功获取到MyAspect 中修改的注解参数值。如下所示:
遗留问题:
- 必须传入该参数才可以获取到修改后的值
- 通过反射方法method.getAnnotation(WebLogAnnotation.class)获取到的是原始值。若@Cached底层也是通过反射实现,则修改不了。
通过反射动态修改自定义注解属性值、SpringBoot实现对自定义注解的切面、自定义注解属性动态赋值