当@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
可以看到是想要的结果
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南