需求上 MyController 中不需要重写父类中方法的逻辑,仅仅注解中 testField 的值不是默认值。
因为不想仅仅为了指定下 testField 而去重写多个方法,所以考虑字类初始化的时候,批量修改 testField 。
但是请求接口的时候,通过观察切面中的日志输出,子类中非重写的方法 method3 的注解对象中的 testField 是被修改为了 test2 ;而请求接口 method1 、method2 的时候,testField 还是 test1,并且切面中输出的注解对象的地址与 static 代码块中输出的不同。
Spring 的 AOP,注解、反射工具类是 hutool 的。
// 注解
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface MyAnnotation {
String testField() default "test1";
}
// 抽象控制器
public abstract class AbstractController{
@MyAnnotation
@RequestMapping(value = "method1", method = RequestMethod.GET)
public RestfulResponse<Boolean> method1() {
return new RestfulResponse<>(true);
}
@MyAnnotation
@RequestMapping(value = "method2", method = RequestMethod.GET)
public RestfulResponse<Boolean> method2() {
return new RestfulResponse<>(true);
}
}
// 继承抽象控制器
@RestController
public class MyController extends AbstractController {
static {
for (Method method : ReflectUtil.getMethods(MyController.class)) {
if (AnnotationUtil.hasAnnotation(method, MyAnnotation.class)) {
MyAnnotation annotation = AnnotationUtil.getAnnotation(method, MyAnnotation.class);
AnnotationUtil.setValue(annotation, "testField", "test2");
// 输出 annotation 地址
}
}
}
@MyAnnotation
@RequestMapping(value = "method3", method = RequestMethod.GET)
public RestfulResponse<Boolean> method3() {
return new RestfulResponse<>(true);
}
}
// 切面
@Aspect
public class MyAspect implements Ordered {
@Around("@annotation(myAnnotation)")
public Object around(ProceedingJoinPoint pjp, MyAnnotation myAnnotation) throws Throwable {
// 输出 myAnnotation 地址、testField 值
return pjp.proceed();
}
}
请问是那里出了问题,为什么切面中获取到的注解对象和 static 中的不是同一个?
1
ChovyChu 2021-05-27 16:45:44 +08:00
知识盲区,坐等大神。
个人感觉可能是顺序问题导致被 default 值覆盖了? |
2
MoHen9 2021-05-27 18:38:22 +08:00 1
不太了解 spring aop 是个什么机制,debug 了一下,发现注入的 MyAnnotation 的实例和通过反射获取的实例是两个不同对象
Method method = ((MethodSignature) pjp.getSignature()).getMethod(); MyAnnotation annotation = method.getAnnotation(MyAnnotation.class); 通过反射获取的 annotion 实例是你想要的,而注入的实例似乎好像大概差不多是在初始化时就缓存好了的。解决问题比较简单,背后的原理什么的,只有坐等大神解答一下了。 |
3
nulIptr 2021-05-27 18:59:04 +08:00
没想明白,什么场景下才运行时修改注解里面属性的值?这跟我理解的注解用途不太一样啊。。。
|
4
persona5 OP @MoHen9 感谢,我也测试一下看看。
@nulIptr 原因我在开头说了,不想仅仅为了指定下 testField 而去重写多个方法。 MyAnnotation 中 testField 的默认值是 test1 对吧,我在 MyController 中需要只用 @MyAnnotation(testField = "test2") 的注解,既需要指定 testField 为 test2 。但是接口方法内的逻辑又没有需要修改的地方,不修改注解中 testField 的值的话。MyController 中就要重写 method1 、method2 了,重写仅仅为了去加上 @MyAnnotation(testField = "test2") 这个注解。 |