当@within 遇到 继承时

x33g5p2x  于9个月前 转载在 其他  
字(3.2k)|赞(0)|评价(0)|浏览(377)

项目中用一个注解做切面,拦截的时候,需要获取注解里的值,当存在继承关系时,拦截到父类方法取注解的值是没问题的,但拦截到子类的方法取注解的值是有问题的,具体看一下例子。

背景

项目中用一个注解做切面,拦截的时候,需要获取注解里的值,父类取值是没问题的,但是子类取值是有问题的,具体看一下例子

例子

  1. 一个自定义注解
  2. @Target({ElementType.METHOD, ElementType.TYPE})
  3. @Retention(RetentionPolicy.RUNTIME)
  4. @Inherited
  5. @Documented
  6. public @interface MyAnnotation {
  7. String value() default "me";
  8. }
  9. 一个普通的父类
  10. @Slf4j
  11. @MyAnnotation("father")
  12. public class Father {
  13. public void hello() {}
  14. public void hello2() {}
  15. }
  16. 一个普通的子类
  17. @Slf4j
  18. @MyAnnotation("son")
  19. public class Son extends Father {
  20. @Override
  21. public void hello2() {}
  22. }
  23. 配置类
  24. @Configuration
  25. @EnableAspectJAutoProxy(exposeProxy = true)
  26. public class Config {
  27. @Bean
  28. public Father father() {
  29. return new Father();
  30. }
  31. @Bean
  32. public Son son() {
  33. return new Son();
  34. }
  35. }
  36. 切面:
  37. @Slf4j
  38. @Aspect
  39. @Order(-1)
  40. @Component
  41. public class MyAspect {
  42. @Before("@within(myAnnotation)")
  43. public void before(JoinPoint point, MyAnnotation myAnnotation) {
  44. Signature signature = point.getSignature();
  45. log.info("{}.{}, annotation value:{}",
  46. signature.getDeclaringType().getSimpleName(), signature.getName(), myAnnotation.value());
  47. }
  48. }
  49. 启动类:
  50. public class Main {
  51. public static void main(String[] args) {
  52. AnnotationConfigApplicationContext context =
  53. new AnnotationConfigApplicationContext(Config.class, MyAspect.class);
  54. Father father = context.getBean("father", Father.class);
  55. father.hello();
  56. father.hello2();
  57. Son son = context.getBean(Son.class);
  58. son.hello();
  59. son.hello2();
  60. }
  61. }
  1. 输出:
  2. 1232 [main] INFO c.e.l.s.a.annotation.demo.MyAspect - Father.hello, annotation value:father
  3. 1241 [main] INFO c.e.l.s.a.annotation.demo.MyAspect - Father.hello2, annotation value:father
  4. 1242 [main] INFO c.e.l.s.a.annotation.demo.MyAspect - Father.hello, annotation value:father
  5. 1248 [main] INFO c.e.l.s.a.annotation.demo.MyAspect - Son.hello2, annotation value:son
  6. 从结果看出:
  7. 访问父类的方法时,获取到的注解的值是没问题的
  8. 但是访问子类的方法时,如果没有重写方法,则获取到的注解的值是父类注解值的内容,如果重写了方法,则获取到的是自己类上加的注解的值

解决

如果你不想要重写方法就能获取到自己类上的注解的值,你可以这样做:

  1. 新加一个注解
  2. @Target({ElementType.METHOD, ElementType.TYPE})
  3. @Retention(RetentionPolicy.RUNTIME)
  4. @Inherited
  5. @Documented
  6. public @interface MyAnnotation2 {
  7. String value() default "me2";
  8. }
  9. 切面增加以下方法:
  10. @Before("@within(myAnnotation2)")
  11. public void before(JoinPoint point, MyAnnotation2 myAnnotation2) {
  12. Signature signature = point.getSignature();
  13. MyAnnotation2 annotation = point.getTarget().getClass().getAnnotation(MyAnnotation2.class);
  14. log.info("--- {}.{}, annotation value:{}",
  15. signature.getDeclaringType().getSimpleName(), signature.getName(), annotation.value());
  16. }
  17. 父类和子类加上新注解
  18. @Slf4j
  19. @MyAnnotation("father")
  20. @MyAnnotation2("father")
  21. public class Father {}
  22. @Slf4j
  23. @MyAnnotation("son")
  24. @MyAnnotation2("son")
  25. public class Son extends Father {}
  1. 再运行一下看一下结果:
  2. 1122 [main] INFO c.e.l.s.a.annotation.demo.MyAspect - Father.hello, annotation value:father
  3. 1127 [main] INFO c.e.l.s.a.annotation.demo.MyAspect - --- Father.hello, annotation value:father
  4. 1139 [main] INFO c.e.l.s.a.annotation.demo.MyAspect - Father.hello2, annotation value:father
  5. 1139 [main] INFO c.e.l.s.a.annotation.demo.MyAspect - --- Father.hello2, annotation value:father
  6. 1141 [main] INFO c.e.l.s.a.annotation.demo.MyAspect - Father.hello, annotation value:father
  7. 1141 [main] INFO c.e.l.s.a.annotation.demo.MyAspect - --- Father.hello, annotation value:son
  8. 1147 [main] INFO c.e.l.s.a.annotation.demo.MyAspect - Son.hello2, annotation value:son
  9. 1147 [main] INFO c.e.l.s.a.annotation.demo.MyAspect - --- Son.hello2, annotation value:son
  10. 可以看到是想要的结果

相关文章