子类可以继承到父类上的注解吗?

在编写自定义注解时,可以通过指定@Inherited注解,申明自定义注解是否可以被继承;@Inherited只能实现类上的注解继承。

实现情况可细分为以下几种

未申明@Inherited 申明了@Inherited
子类的类上能否继承到父类的类上的注解? ×
子类实现了父类上的抽象方法,这个方法能否继承到注解? × ×
子类继承了父类上的方法,这个方法能否继承到注解?
子类重写了父类上的方法,这个方法能否继承到注解? × ×

spring的注解,即便该注解没有被继承到子类上,但子类同样能享有这个注解带来的效果,这可能和spring的注解扫描和bean加载机制有关。

代码示例

自定义注解

package test.annotation;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
/**
* 自定义注解
*/
@Inherited //申明注解可以被继承
@Retention(java.lang.annotation.RetentionPolicy.RUNTIME) //可以通过反射读取注解
public @interface MyAnnotation {
String value();
}

父类

package test.annotation;
@MyAnnotation(value = "类名上的注解")
public abstract class ParentClass { @MyAnnotation(value = "父类的abstractMethod方法")
public abstract void abstractMethod(); @MyAnnotation(value = "父类的doExtends方法")
public void doExtends() {
System.out.println(" ParentClass doExtends ...");
} @MyAnnotation(value = "父类的doHandle方法")
public void doHandle(){
System.out.println(" ParentClass doHandle ...");
}
}

子类

package test.annotation;
public class SubClass extends ParentClass{ //子类实现父类的抽象方法
@Override
public void abstractMethod() {
System.out.println("子类实现父类的abstractMethod抽象方法");
} //子类继承父类的doExtends方法,直接调用父类方法 //子类重写父类的doHandle方法
@Override
public void doHandle(){
System.out.println("子类覆盖父类的doHandle方法");
}
}

测试类

package test.annotation;

import java.lang.reflect.Method;

public class MainTest {
public static void main(String[] args) throws SecurityException,NoSuchMethodException { Class<SubClass> clazz = SubClass.class; if (clazz.isAnnotationPresent(MyAnnotation.class)) {
MyAnnotation cla = clazz.getAnnotation(MyAnnotation.class);
System.out.println("子类继承到父类类上Annotation,其信息如下:"+cla.value());
} else {
System.out.println("子类没有继承到父类类上Annotation");
}
// 实现抽象方法测试
Method method = clazz.getMethod("abstractMethod", new Class[] {});
if (method.isAnnotationPresent(MyAnnotation.class)) {
MyAnnotation ma = method.getAnnotation(MyAnnotation.class);
System.out.println("子类实现父类的abstractMethod抽象方法,继承到父类抽象方法中的Annotation,其信息如下:"+ma.value());
} else {
System.out.println("子类实现父类的abstractMethod抽象方法,没有继承到父类抽象方法中的Annotation");
}
//重写测试
Method methodOverride = clazz.getMethod("doExtends", new Class[] {});
if (methodOverride.isAnnotationPresent(MyAnnotation.class)) {
MyAnnotation ma = methodOverride.getAnnotation(MyAnnotation.class);
System.out.println("子类继承父类的doExtends方法,继承到父类doExtends方法中的Annotation,其信息如下:"+ma.value());
} else {
System.out.println("子类继承父类的doExtends方法,没有继承到父类doExtends方法中的Annotation");
}
//继承测试
Method method3 = clazz.getMethod("doHandle", new Class[] {});
if (method3.isAnnotationPresent(MyAnnotation.class)) {
MyAnnotation ma = method3.getAnnotation(MyAnnotation.class);
System.out.println("子类覆盖父类的doHandle方法,继承到父类doHandle方法中的Annotation,其信息如下:"+ma.value());
} else {
System.out.println("子类覆盖父类的doHandle方法,没有继承到父类doHandle方法中的Annotation");
}
}
}

编写自定义注解时未申明@Inherited的运行结果:

子类没有继承到父类类上Annotation

子类实现父类的abstractMethod抽象方法,没有继承到父类抽象方法中的Annotation

子类继承父类的doExtends方法,继承到父类doExtends方法中的Annotation,其信息如下:父类的doExtends方法

子类覆盖父类的doHandle方法,没有继承到父类doHandle方法中的Annotation

编写自定义注解时申明了@Inherited的运行结果:

子类继承到父类类上Annotation,其信息如下:类名上的注解

子类实现父类的abstractMethod抽象方法,没有继承到父类抽象方法中的Annotation

子类继承父类的doExtends方法,继承到父类doExtends方法中的Annotation,其信息如下:父类的doExtends方法

子类覆盖父类的doHandle方法,没有继承到父类doHandle方法中的Annotation

重写方法如何实现继承注解?

@Inherited只能实现类上的注解继承;要想实现重写父类方法上注解的继承,可以通过反射在继承链上找到方法上的注解,但实现很繁琐,还需要考虑桥接方法。

幸好Spring提供了AnnotatedElementUtils类,来方便我们处理注解的继承问题。

// spring提供的工具类 AnnotatedElementUtils
MyAnnotation annotation = AnnotatedElementUtils.getMergedAnnotation(SubClass.class.getMethod("doHandle"), MyAnnotation.class);

调用AnnotatedElementUtils的findMergedAnnotation()方法,可以帮助我们找到父类和接口、父类方法和接口方法上的注解,实现一键找到继承链的注解。

@RequestMapping注解能否被继承?

经过测试,发现子类如果重写了父类的方法,确实不能继承被重写方法的注解,但是子类却可以享有父类中该注解带来的效果。

试了一下spring的注解,即便该注解没有被继承到子类上,但子类同样能享有这个注解带来的效果,这可能和spring的注解扫描和bean加载机制有关。

代码示例

public abstract class AbstractParent {

    @PostConstruct
protected void init() {
System.out.println("AbstractParent的init方法");
}
}
@Component
public class Child extends AbstractParent{ @Override
protected void init() {
System.out.println("Child的init方法");
} @PostConstruct
private void init1() {
System.out.println("Child的init1方法");
}
}

启动后输出:



如果没有重写,子类@PostConstruct方法执行前会先执行父类@PostConstruct方法。

注解的合并使用

合并注解的含义

  1. 注解只在springboot中有用
  2. 注解本身并不能被注解继承
  3. 注解合并需要使用:@AliasFor

合并注解的案例

@RestController = @Controller + @ResponseBody

把多个注解合并成1个,这里把@RestController和@RequestMapping合并为一个@PathRestController

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; @Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@RestController
@RequestMapping
public @interface PathRestController {
@AliasFor("path")
String[] value()default {}; @AliasFor("value")
String[] path()default {};
}

自定义注解使用场景

自定义注解+拦截器或者AOP切面编程,使用自定义注解来设计框架,使得代码看起来非常优雅。

常见使用场景:

接口使用自定义注解+拦截器,实现登录校验

接口使用自定义注解+AOP,实现记录操作日志

接口使用自定义注解,实现控制请求限流和防止表单重复提交

实体类使用自定义注解,实现校验字段唯一性

实体类字段使用自定义注解,实现数据脱敏

Java子类是否能继承父类上的注解的更多相关文章

  1. 转:Java中子类是否可以继承父类的static变量和方法而呈现多态特性

    原文地址:Java中子类是否可以继承父类的static变量和方法而呈现多态特性 静态方法 通常,在一个类中定义一个方法为static,那就是说,无需本类的对象即可调用此方法,关于static方法,声明 ...

  2. Java中子类是否可以继承父类的static变量和方法而呈现多态特性

    静态方法 通常,在一个类中定义一个方法为static,那就是说,无需本类的对象即可调用此方法,关于static方法,声明为static的方法有以下几条限制: 它们仅能调用其他的static 方法. 它 ...

  3. @interface __ annotation 子类可以继承到父类上的注解吗--有结论了

    博客分类: Java/J2se   作者:赵磊 博客:http://elf8848.iteye.com 不了解注解基础知识的请先看<JDK 5 Annotation\注解\注释\自定义注解> ...

  4. Java -- 子类使用super调用父类的方法A,A 调用了方法B,子类也override方法B,那么super.A()最终调用到了子类的B方法

    public class SuperClass{ public void printA(){ System.out.print("SuperClass-printA"); prin ...

  5. java 子类不能继承父类的static方法

    先来看一段代码 /** * Created by bjchengpeng on 2018/7/19. */ /**运行结果 * woof * woofaa * * woof * Basenjiaa * ...

  6. Java中子类能继承父类的私有属性吗?

    前段时间去听老师讲课的时候,老师告诉我子类是可以继承父类所有的属性和方法的.当时我是极其疑惑的,因为之前学校考试时这个考点我记得很清楚:子类只能继承父类的非私有属性和方法.老师给我的解释是这样的--先 ...

  7. javascript中子类如何继承父类

    参考阮一峰的文章:http://javascript.ruanyifeng.com/oop/inheritance.html#toc4 function Shape() { this.x = 0; t ...

  8. Net基础篇_学习笔记_第十二天_面向对象继承(父类和子类)

    继承 我们可能会在一些类中,写一些重复的成员,我们可以将这些重复的成员,单独的封装到一个类中,作为这些类的父类.Student.Teacher.Driver 子类  派生类Person         ...

  9. (转)Java:类与继承

    原文地址: http://www.cnblogs.com/dolphin0520/p/3803432.html 对于面向对象的程序设计语言来说,类毫无疑问是其最重要的基础.抽象.封装.继承.多态这四大 ...

  10. Java:类与继承

    Java:类与继承 对于面向对象的程序设计语言来说,类毫无疑问是其最重要的基础.抽象.封装.继承.多态这四大特性都离不开类,只有存在类,才能体现面向对象编程的特点,今天我们就来了解一些类与继承的相关知 ...

随机推荐

  1. .NET有哪些好用的定时任务调度框架

    前言 定时任务调度的相关业务在日常工作开发中是一个十分常见的需求,经常有小伙伴们在技术群提问:有什么好用的定时任务调度框架推荐的?今天大姚给大家分享5个.NET开源.简单.易用.免费的任务调度框架,帮 ...

  2. cesium教程3-加载3dtile模型,并调整位置

    直接上示例代码: <!DOCTYPE html> <html lang="en"> <head> <meta charset=" ...

  3. Nifi:Nifi中的Controller Service

    Service简介 首先Nifi中的Controller Service 和我们MVC概念中的Controller Service不是一个概念,Nifi中的Controller Service更像是和 ...

  4. P3667 Bovine Genomics Hash+二分题解

    砂金听说了你在学字符串,于是在CLOI里出了道题给你 P3667 Bovine Genomics 题链:洛谷 hzoi提高 \(hash\)基础题. 思路是二分答案,\(check\)中比较每一个区间 ...

  5. Python基础篇(安装)

    Python简介 Python是Guido van Rossum发布于1991年的一种计算机程序设计语言.是一种动态的.面向对象的脚本语言,是一种解释型的,弱类型的高级计算机语言.需要注意的是pyth ...

  6. linux文件权限管理:文件权限类型,文件权限影响,设定文件权限,取消文件权限

    目录 一.关于文件权限 二.查看文件权限 三.linux下常见文件类型 四.linux下常见的文件权限 五.权限对文件和目录的影响 六.文件的用户分类 七.更改文件的属主和属组 八.一个文件取消所有权 ...

  7. 二进制安装Kubernetes(k8s)v1.30.1

    二进制安装Kubernetes(k8s)v1.30.1 https://github.com/cby-chen/Kubernetes 开源不易,帮忙点个star,谢谢了 介绍 kubernetes(k ...

  8. 初步搭建一个自己的对象存储服务---Minio

    docker安装 1.拉取镜像 docker pull minio/minio 2.启动镜像 docker run -p 9000:9000 -p 9001:9001 --name minio -d ...

  9. Anaconda安装Python的seaborn库

      本文介绍在Anaconda的环境中,安装Python语言中,常用的一个绘图库seaborn模块的方法.   seaborn模块是基于Matplotlib的数据可视化库,它提供了一种更简单.更漂亮的 ...

  10. 震惊!docker镜像还有这些知识,你都知道吗?----镜像(一)

    镜像操作命令表格 docker image 子命令 docker子命令 功能 docker image build docker build 从Dockerfile开始构建镜像 docker imag ...