大厂面试题典-注解可以继承吗,show me code?
注解可为Java代码提供元数据,框架也会利用注解暴露功能,比如Spring框架中的@Service
、@Controller
。
框架可通过类或方法等元素上标记的注解了解它们的功能或特性,并以此来启用或执行相应的功能。通过注解而非API调用来配置框架,属于声明式交互,可以简化框架配置,也可和框架解耦。
你也许认为类继承后,类的注解也可继承,子类重写父类方法后,父类方法上的注解也能作用于子类,确定吗?
1 案例
-
自定义注解
-
定义被该注解标记的类Parent,设置value为Class字符串,foo方法也标记了@MyAnnotation注解
-
子类Child继承Parent父类,并重写父类的foo方法,子类的foo方法和类上都没有@MyAnnotation注解。
-
通过反射分别获取Parent和Child的类和方法的注解信息,并输出注解的value属性的值(如果注解不存在则输出空字符串):
-
日志输出
父类的类和方法上的注解都可正确获得,但子类的类和方法却不能。即子类及子类的方法,无法自动继承父类和父类方法上的注解。
2 @Inherited
元注解实现注解的继承
- 日志输出
子类可以获得父类类上的注解;子类的foo虽是重写父类方法,并且注解本身也支持继承,但还是无法获得方法上的注解。
因为@Inherited
只能实现类上的注解继承。
3 方法上注解的继承
可通过反射在继承链上找到方法上的注解。但实现很繁琐,还需要考虑桥接方法。
幸好Spring提供了AnnotatedElementUtils类。
3.1 AnnotatedElementUtils工具类
对@Inherited
的支持
遵循get语义的方法将遵循Java的@Inherited
注解的约定,除了在本地声明的批注(包括自定义组成的注解)优于继承的注解之外。相反,遵循find语义的方法将完全忽略@Inherited
的存在,因为find搜索算法手动遍历类型和方法层次结构,从而隐式支持注解继承,而无需@Inherited
。
Find V.S Get Semantics
此类中的方法使用的搜索算法遵循find或get语义。
Get 语义
仅限于搜索存在于AnnotatedElement
上的注解(即在本地声明或继承)或在AnnotatedElement上方的注解层次结构中声明的注释。
Find 语义
更加详尽,提供了获取语义以及对以下内容的支持:
- 搜索接口(如果带注释的元素是类)
- 搜索超类(如果带注释的元素是一个类)
- 解析桥接方法(如果带注释的元素是方法)
- 如果带注解的元素是方法,则在接口中搜索方法
- 如果带注解的元素是方法,则在超类中搜索方法
如下俩方法其实也很相像,有何区别呢?
findAllMergedAnnotations
Find 对应 SearchStrategy.TYPE_HIERARCHY
其findMergedAnnotation方法可找出父类和接口、父类方法和接口方法上的注解,并可以处理桥接方法,实现一键找到继承链的注解:
getAllMergedAnnotations
Get对应 SearchStrategy.INHERITED_ANNOTATIONS
:
4 Spring的@Service、@Controller会支持继承吗?
我们假设继承后,RequestMapping对应的在父子类都能找到,处理起来肯定会很麻烦,在加上这几个注解默认都是单例的,所以是不能继承的。其实spring 官方对此也有回应。
参考
- https://github.com/spring-projects/spring-framework/issues/8859
文章来源: javaedge.blog.csdn.net,作者:JavaEdge.,版权归原作者所有,如需转载,请联系作者。
原文链接:javaedge.blog.csdn.net/article/details/109830695
- 点赞
- 收藏
- 关注作者
评论(0)