Java中自定义注解的使用

一般来说,市面上有一些的框架,企业都不会直接拿过来就用,通过会做二次开发或封装,为了更加适配自己的开发规范和业务。那么在封装或适配的过程中,自定义注解就起着比较重要的作用。

1 注解定义、原理及作用

1.1 什么是注解

Annotation(注解)是Java5引入的新特性。它提供了一种安全的类似于注解的机制,它可以用来将任何的信息或元数据(metadata)与程序元素(类、方法、成员、变量等)进行关联。为程序的类、方法、成员变量等加上更加直观的说明,这些说明信息是与程序的业务逻辑无关,并且供指定的工具或框架使用。Annotation就像一种修饰符一样,应用于包、类型、构造方法、普通方法、成员变量、参数及本地变量的声明语句中。

注解是附加在代码中的一些元信息,用于一些工具在编译、运行时,进行解析和使用,起到说明、配置的功能。
注解不会也不能影响代码的实际逻辑。仅仅起到辅助的作用。包含在java.lang.annotation包中。

1.2 注解的用处

  1. 生成文档。这是最常见的,也是java中提供最早的注释。例如:@param @return等
  2. 跟踪代码依赖性,实现替代配置文件功能。比如@Bean、@Service等,并且可以遇见的是未来的开发,将大量使用注解。
  3. 在编译时进行格式检查。如@Override放在方法上,如果该方法不是覆盖了父类的方法,则编译时就能检查出来。

1.3 注解的原理

注解的本质就是一个继承了Annotation的特殊接口,其具体实现类是Java运行时生成的动态代理类,而我们通过反射获取注解时,返回的是Java运行时生成的动态代理对象$Proxy1。通过代理对象调用自定义注解(接口)的方法,会最终调用AnnotationInvocationHandler的invoke方法。该方法会从memberValues这个Map中索引出对应的值。而memberValues的来源是Java常量池。

1.4 元注解

java.lang.anntotaion提供了四种元注解,专门注解其他的注解(在自定义注解的时候,需要用到元注解):

  • @Documented 注解是否将包含在JavaDoc中
  • @Retention 什么时候使用该注解
  • @Target 注解用于什么地方
  • @Inherited 是否允许子类继承该注解
  1. @Retention - 定义该注解的生命周期
- RetentionPolicy.SOURCE : 在编译阶段丢弃。这些注解在编译结束之后就不再有任何意义。因此不会写入字节码。@Override,@SuppressWarnings,@Deprecated都属于这类注解。
- RetentionPolicy.CLASS : 在类加载的时候丢弃。在字节码文件的处理中有用。`注解默认使用这种方式`
- RetentionPolicy.RUNTIME : 始终不会丢弃,运行期也保留该注解,因此可以使用反射机制读取该注解的信息。我们`自定义的注解通常使用这种方式`。
  1. Target - 表示该注解用于什么地方。默认值为任何元素。
- ElementType.CONSTRUCTOR: 用于描述构造器
- ElementType.FIELD: 成员变量、对象、属性(包括enum实例)
- ElementType.LOCAL_VARIABLE: 用于描述局部变量
- ElementType.METHOD: 用于描述方法
- ElementType.PACKAGE: 用于描述包
- ElementType.PARAMETER: 用于描述参数
- ElementType.TYPE: 用于描述类、接口(包括注解类型) 或enum声明
  1. @Documented - 一个简单的Annotations标记注解,表示是否将注解信息添加到java文档中
  2. @Inherited - 定义该注解和子类的关系
@Inherited元注解是一个标记注解。阐述了某个被标注的类型是被继承的。如果一个使用了@Inherited的注解
被加在了某个类上,那么这个注解将被用于该class的子类。

1.5 Java内置的三大注解(@Override、@Deprecated、@SuppressWarnings)

除上述四种元注解外,JDK预定了另外三种注解:

@Override
@Deprecated
@SuppressWarnings

1.)@Override

java.lang.Override 是一个标记类型注解,它被用作标注方法。它说明了被标注的方法重载了父类的方法,起到了断言的作用。如果我们使用了这种注解在一个没有覆盖父类方法的方法时,java 编译器将以一个编译错误来警示。

2.)@Deprecated

Deprecated 也是一种标记类型注解。当一个类型或者类型成员使用@Deprecated 修饰的话,编译器将不鼓励使用这个被标注的程序元素。所以使用这种修饰具有一定的“延续性”:如果我们在代码中通过继承或者覆盖的方式使用了这个过时的类型或者成员,虽然继承或者覆盖后的类型或者成员并不是被声明为@Deprecated,但编译器仍然要报警。

  • 表明已经过时,不推荐使用

3.)@SuppressWarnings

SuppressWarning 不是一个标记类型注解。它有一个类型为String[] 的成员,这个成员的值为被禁止的警告名。对于javac 编译器来讲,被-Xlint 选项有效的警告名也同样对@SuppressWarings 有效,同时编译器忽略掉无法识别的警告名。@SuppressWarnings(“unchecked”)

  • 用于抑制编译器的检查。

2 自定义注解实战

自定义注解类编写的一些规则:

  1. Annotation 型定义为@interface, 所有的Annotation 会自动继承java.lang.Annotation这一接口,并且不能再去继承别的类或是接口.
  2. 参数成员只能用public 或默认(default) 这两个访问权修饰
  3. 参数成员只能用基本类型byte、short、char、int、long、float、double、boolean八种基本数据类型和String、Enum、Class、annotations等数据类型,以及这一些类型的数组.
  4. 要获取类方法和字段的注解信息,必须通过Java的反射技术来获取 Annotation 对象,因为你除此之外没有别的获取注解对象的方法
  5. 注解也可以没有定义成员,,不过这样注解就没啥用了

自定义注解需要使用到元注解

- 自定义注解会自动继承Annotation接口,无法在继承别的类或接口
- 参数只能用public或默认修饰
- 参数只能用八大基本数据类型+String+Enum等及该类型的数组
- 只能通过反射获取类方法和字段的注解信息
- 注解中可无成员,但那样就没有意义了

①自定义一个水果有关注解

@FruitName:

/*** 水果名称注解* @author 夏末*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FruitName {String value() default "";
}

@FruitColor:

/*** @author 夏末*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FruitColor {//颜色枚举public enum Color{BLUE, RED, GREEN}//颜色属性,默认是绿色Color fruitColor() default Color.GREEN;
}

@FruitProvider:

/*** @author 夏末* @description TODO* @date 2022/9/29 11:38*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
//水果供应商注解
public @interface FruitProvider {//水果供应商编号public int id() default -1;//水果供应商名称public String name() default "";//供应商地址public String address() default "";
}

②定义注解处理器FruitInfoHandler

/*** @author 夏末* @description 注解处理器* @date 2022/9/29 11:40*/
public class FruitInfoHandler {public static void getFruitInfo(Class<?> clazz){String strFruitName = " 水果名称: ";String strFruitColor = " 水果颜色: ";String strFruitProvider = " 供应商信息: ";Field[] fields = clazz.getDeclaredFields();for(Field field : fields){if(field.isAnnotationPresent(FruitName.class)){//获取水果名FruitName fruitName = (FruitName)field.getAnnotation(FruitName.class);strFruitName = strFruitName + fruitName.value();System.out.println(strFruitName);} else if(field.isAnnotationPresent(FruitColor.class)){//获取水果颜色FruitColor fruitColor = field.getAnnotation(FruitColor.class);strFruitColor = strFruitColor + fruitColor.fruitColor().toString();System.out.println(strFruitColor);} else if (field.isAnnotationPresent(FruitProvider.class)){FruitProvider fruitProvider = field.getAnnotation(FruitProvider.class);strFruitProvider = "供应商编号: " + fruitProvider.id() + "供应商名称:" + fruitProvider.name() +"供应商地址: " + fruitProvider.address();System.out.println(strFruitProvider);}}}
}

③使用注解(创建某个类并使用注解)

Apple.java:

/*** @author 夏末* @description 定义一个水果类,并使用注解* @date 2022/9/29 11:56*/
public class Apple {@FruitName("Apple")private String appleName;@FruitColor(fruitColor = FruitColor.Color.RED)private String appleColor;@FruitProvider(id=1, name = "红富士集团", address = "长虹大道")private String appleProvider;public String getAppleName() {return appleName;}public void setAppleName(String appleName) {this.appleName = appleName;}public String getAppleColor() {return appleColor;}public void setAppleColor(String appleColor) {this.appleColor = appleColor;}public String getAppleProvider() {return appleProvider;}public void setAppleProvider(String appleProvider) {this.appleProvider = appleProvider;}
}

④测试结果

public class Test {public static void main(String[] args) {FruitInfoHandler.getFruitInfo(Apple.class);// 水果名称: Apple// 水果颜色: RED//供应商编号: 1供应商名称:红富士集团供应商地址: 长虹大道}
}

参考文章:
https://www.cnblogs.com/UncleWang001/p/11044902.html
https://www.cnblogs.com/zhongqifeng/p/14693074.html

Java中自定义注解的使用相关推荐

  1. 谈谈 Java 中自定义注解及使用场景

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 作者:快给我饭吃 www.jianshu.com/p/a7bedc ...

  2. 五十八、深入了解 Java 中的注解和自定义注解

    @Author:Runsen @Date:2020/7/9 人生最重要的不是所站的位置,而是内心所朝的方向.只要我在每篇博文中写得自己体会,修炼身心:在每天的不断重复学习中,耐住寂寞,练就真功,不畏艰 ...

  3. springboot项目中自定义注解的使用总结、java自定义注解实战(常用注解DEMO)

    初学spring的时候使用注解总觉得使用注解很神奇,加一个注解就能实现想要的功能,很好奇,也想自己根据需要写一些自己实现的自定义注解.问题来了,自定义注解到底是什么?肯定会有人和我一样有这个疑惑,我根 ...

  4. 详解Java中的注解

    在Java中,注解(Annotation)引入始于Java5,用来描述Java代码的元信息,通常情况下注解不会直接影响代码的执行,尽管有些注解可以用来做到影响代码执行. 注解可以做什么 Java中的注 ...

  5. 22、java中的注解

    注解是什么? 注解可以理解成注释.标记.标签的意思,用来标记类.方法等.就相当于现实生活中的一些事物,上边贴一个标签或者写一些注释性文字来描述它可以用来做什么.怎么用.何时用等信息.Java中的注解也 ...

  6. Java中的注解是如何工作的

    转载自 Java中的注解是如何工作的? 自Java5.0版本引入注解之后,它就成为了Java平台中非常重要的一部分.开发过程中,我们也时常在应用代码中会看到诸如@Override,@Deprecate ...

  7. 深入理解JAVA中的注解

    本文来说下JAVA中的注解,这个技术虽然我们每天都在使用,但是不一定知道其实现原理.本文来详细介绍下JAVA中注解相关的知识. 文章目录 概述 什么是注解 注解的本质是什么 注解体系图 常用元注解 @ ...

  8. Java Annotation自定义注解详解

    在开发过程中总能用到注解,但是从来没有自己定义过注解.最近赋闲在家,研究整理了一番,力求知其然知其所以然. 本文会尝试描述什么是注解,以及通过一个Demo来说明如何在程序中自定义注解.Demo没有实际 ...

  9. Java中的注解(Annotation)处理器解析

    Java中的注解(Annotation)是一个很神奇的东西,特别现在有很多Android库都是使用注解的方式来实现的.一直想详细了解一下其中的原理.很有幸阅读到一篇详细解释编写注解处理器的文章.本文的 ...

最新文章

  1. 超nb的网页标签弹窗js代码!
  2. 双线性插值(Bilinear Interpolation)
  3. MyBatis框架使用(一)
  4. 云专网和云专线的区别_云专线的优势及应用场景
  5. 解决spring-session升级到2.0.0报错的问题
  6. python安装第三方库-常见错误解决
  7. 一分钟实现纯CSS全屏滚动特效
  8. No module named ‘yaml‘错误解决办法
  9. pdf内容怎么复制到word文档里_PDF转Word要收费?这4种免费实用的方法送你,一分钟统统能搞定...
  10. mysql workbench修改密码_更改MySQL用户密码
  11. 根据文件后缀名显示对应类型缩略图
  12. 调色板的原理与显示模式
  13. 零基础入门Jetson Nano——软件篇
  14. 边缘计算在视频直播场景的应用与实践
  15. python缺省值_python函数缺省值
  16. SHEN ZHEN归来!
  17. python三级菜单_Python 三级菜单
  18. 01——计算机系统基础
  19. 怎样用SolidWorks2013打开.igs、.x_t等格式文件
  20. Simulink-过零检测与代数环

热门文章

  1. R语言实战笔记--第四五章 数据管理
  2. LOL链接不上服务器重装了还是显示连接不上服务器,可能的解决办法
  3. oppo手机android4.4.4,OPPO便签
  4. Linux:通过shell批量ping网站、ip延迟
  5. sort排序函数用法
  6. java常用英文翻译
  7. 大数据量数据库优化问题学习
  8. 将CorelDRAW文件转成PSD分层文件详解
  9. 检测到你的手机处于root环境_网络安全小黑板 | 如何正确安装和管理手机应用程序...
  10. 闲聊蓝桥杯JAVA - 路径之谜