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

在编写自定义注解时,可以通过指定@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. 02.go-admin IDE配置配置命令启动方式讲解笔记

    目录 go-admin版本 视频地址 一.代码地址 二.在线文档 三.首次配置需要初始化数据库资源信息(已初始化过数据库的,跳过此步) 配置数据库迁移 五.配置启动项目,用goland IDE进行启动 ...

  2. postgresql性能优化1:min和max的性能

    select max(datatime) as id from mytable ---全表检索,时间慢执行时间5分钟 select max(datatime) as id from mytable w ...

  3. Centos 密码过期问题 password has expired

    1.这个主要是由/etc/login.defs参数文件中的一些参数控制的的.它主要用于用户账号限制PASS_MAX_DAYS 60     #密码最大有效期,此处参数PASS_MAX_DAYS为60, ...

  4. 因为我的一次疏忽而带来的golang1.23新特性

    距离golang 1.23发布还有两个月不到,按照惯例很快要进入1.23的功能冻结期了.在冻结期间不会再添加新功能,已经添加的功能不出大的意外一般也不会被移除.这正好可以让我们提前尝鲜这些即将到来的新 ...

  5. EDP .Net开发框架--自动化日志

    平台下载地址:https://gitee.com/alwaysinsist/edp 自动化日志不需要额外调用日志相关功能即可无感实现程序集方法调用的日志记录. 创建业务逻辑处理类 public cla ...

  6. 【c#】JavaScriptSerializer 不序列化null值

    首先引用dll :System.Web.Extensions. 再自定义转换器代码如下: public class JavaScriptSerilizeConvert : JavaScriptConv ...

  7. Dubbo SPI扩展机制源码详解(基于2.7.10)

    Dubbo SPI 一. 概述 本文主要分享 Dubbo 的拓展机制 SPI. 想要理解 Dubbo ,理解 Dubbo SPI 是非常必须的.在 Dubbo 中,提供了大量的拓展点,基于 Dubbo ...

  8. OpenQA.Selenium.WebDriverException The HTTP request to the remote WebDriver server for URL timed out

    OpenQA.Selenium.WebDriverException:"The HTTP request to the remote WebDriver server for URL htt ...

  9. Flutter(七):Flutter混合开发--接入现有原生工程(iOS+Android)

    在上一篇文章Flutter(六):Flutter_Boost接入现有原生工程(iOS+Android)中介绍了Flutter_Boost的接入方法,这一篇将介绍Flutter自带的接入方法. 新建工程 ...

  10. GPT-4o和GPT-4有什么区别?我们还需要付费开通GPT-4?

    GPT-4o 是 OpenAI 最新推出的大模型,有它的独特之处.那么GPT-4o 与 GPT-4 之间的主要区别具体有哪些呢?今天我们就来聊聊这个问题. 目前来看,主要是下面几个差异. 响应速度 G ...