当@within 遇到 继承时

背景

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

例子

一个自定义注解
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface MyAnnotation {
    String value() default "me";
}

一个普通的父类
@Slf4j
@MyAnnotation("father")
public class Father {
    public void hello() {}

    public void hello2() {}
}

一个普通的子类
@Slf4j
@MyAnnotation("son")
public class Son extends Father {
    @Override
    public void hello2() {}
}

配置类
@Configuration
@EnableAspectJAutoProxy(exposeProxy = true)
public class Config {

    @Bean
    public Father father() {
        return new Father();
    }

    @Bean
    public Son son() {
        return new Son();
    }
}

切面:
@Slf4j
@Aspect
@Order(-1)
@Component
public class MyAspect {
    @Before("@within(myAnnotation)")
    public void before(JoinPoint point, MyAnnotation myAnnotation) {
        Signature signature = point.getSignature();
        log.info("{}.{}, annotation value:{}",
                signature.getDeclaringType().getSimpleName(), signature.getName(), myAnnotation.value());
    }
}

启动类:
public class Main {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context =
                new AnnotationConfigApplicationContext(Config.class, MyAspect.class);
        Father father = context.getBean("father", Father.class);
        father.hello();
        father.hello2();

        Son son = context.getBean(Son.class);
        son.hello();
        son.hello2();
    }
}
输出:

1232 [main] INFO  c.e.l.s.a.annotation.demo.MyAspect - Father.hello, annotation value:father 
1241 [main] INFO  c.e.l.s.a.annotation.demo.MyAspect - Father.hello2, annotation value:father 
1242 [main] INFO  c.e.l.s.a.annotation.demo.MyAspect - Father.hello, annotation value:father 
1248 [main] INFO  c.e.l.s.a.annotation.demo.MyAspect - Son.hello2, annotation value:son 


从结果看出:
访问父类的方法时,获取到的注解的值是没问题的
但是访问子类的方法时,如果没有重写方法,则获取到的注解的值是父类注解值的内容,如果重写了方法,则获取到的是自己类上加的注解的值

解决

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

新加一个注解
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface MyAnnotation2 {
    String value() default "me2";
}

切面增加以下方法:
    @Before("@within(myAnnotation2)")
    public void before(JoinPoint point, MyAnnotation2 myAnnotation2) {
        Signature signature = point.getSignature();
        MyAnnotation2 annotation = point.getTarget().getClass().getAnnotation(MyAnnotation2.class);
        log.info("--- {}.{}, annotation value:{}",
                signature.getDeclaringType().getSimpleName(), signature.getName(), annotation.value());
    }


父类和子类加上新注解
@Slf4j
@MyAnnotation("father")
@MyAnnotation2("father")
public class Father {}
@Slf4j
@MyAnnotation("son")
@MyAnnotation2("son")
public class Son extends Father {}
再运行一下看一下结果:

1122 [main] INFO  c.e.l.s.a.annotation.demo.MyAspect - Father.hello, annotation value:father 
1127 [main] INFO  c.e.l.s.a.annotation.demo.MyAspect - --- Father.hello, annotation value:father 
1139 [main] INFO  c.e.l.s.a.annotation.demo.MyAspect - Father.hello2, annotation value:father 
1139 [main] INFO  c.e.l.s.a.annotation.demo.MyAspect - --- Father.hello2, annotation value:father 
1141 [main] INFO  c.e.l.s.a.annotation.demo.MyAspect - Father.hello, annotation value:father 
1141 [main] INFO  c.e.l.s.a.annotation.demo.MyAspect - --- Father.hello, annotation value:son 
1147 [main] INFO  c.e.l.s.a.annotation.demo.MyAspect - Son.hello2, annotation value:son 
1147 [main] INFO  c.e.l.s.a.annotation.demo.MyAspect - --- Son.hello2, annotation value:son 

可以看到是想要的结果
posted @ 2022-11-22 16:23  eaglelihh  阅读(118)  评论(0编辑  收藏  举报