使用反射处理Java批注

在上一篇有关Java注释的文章中,我概述了一个最近的用例,并为您提供了一些自定义注释的示例以及如何使用它们。

在本文中,我将更进一步,并为您提供一些自定义注释的示例,以及如何使用Java Reflection API处理这些自定义注释。 学习完本教程后,您应该对自定义注释可以提供的简单性和灵活性有了更好的了解。 因此,让我们深入研究代码!

自定义注释清单

我今天为示例代码创建了三个不同的注释,分别是DoItLikeThisDoItLikeThatDoItWithAWhiffleBallBat注释。 每个注释针对的是不同的元素类型,并且具有稍微不同的属性,因此我可以向您展示如何查找和相应地处理它们。

喜欢这个注释

DoItLikeThis注释针对ElementType TYPE,这使其仅可用于Java类型。 该批注具有三个可选元素description,action和一个布尔字段shouldDoItLikeThis。 如果在使用此批注时不为这些元素提供任何值,则它们将默认为指定的值。

package com.keyhole.jonny.blog.annotations;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** Annotation created for doing it like this.*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface DoItLikeThis {/*** @return - The description.*/String description() default "";/*** @return - The action.*/String action() default "";/*** @return - Should we be doing it like this.*/boolean shouldDoItLikeThis() default false;}

像注释一样

DoItLikeThat注释是仅针对Java字段的注释。 此批注还具有一个类似的布尔元素,名称为ShouldDoItLikeThat,它没有指定默认值,因此在使用批注时是必选元素。 批注还包含一个定义为String数组的元素,该元素将包含应检查的用户角色列表。

package com.keyhole.jonny.blog.annotations;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** Annotation created for doing it like that* instead of like this.*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DoItLikeThat {/*** @return - Should we be doing it like that.*/boolean shouldDoItLikeThat();/*** @return - List of user roles that can do it like that.*/String[] roles() default{};}

DoWWithAWhiffleBallBat批注

DoItWithAWhiffleBallBat注释旨在仅与方法一起使用,并且与其他注释类似。 它也有一个类似的布尔元素,这个名字叫做shouldDoItWithAWhiffleBallBat。 还定义了另一个元素,该元素使用WhiffleBallBat枚举定义了可用的不同类型的Whiffle球棒,默认为经典的黄色经典Whiffle球棒。

package com.keyhole.jonny.blog.annotations;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** When you can't do it like this or do it like that,* do it with a whiffle ball bat.*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DoItWithAWhiffleBallBat {/*** @return - Should we be doing it with a whiffle ball bat.*/boolean shouldDoItWithAWhiffleBallBat() default false;/*** @return - Sweet, which type of whiffle ball bat?*/WhiffleBallBat batType() default WhiffleBallBat.YELLOW_PLASTIC;}

带注释的类

现在我们已经为示例定义了注释,我们需要几个类进行注释。 每个类都提供了使用指定元素以及依赖默认值的注释的示例用法。 还包括其他未注释的字段和方法,因此注释处理器不应对其进行处理。 这是两个示例类的源代码:

带注释的一类

package com.keyhole.jonny.blog.annotations;import java.util.Date;@DoItLikeThis
public class AnnotatedOne implements AnnotatedClass {@DoItLikeThat(shouldDoItLikeThat = false)private String field1;@DoItLikeThat(shouldDoItLikeThat = true, roles = { "admin", "root" })private String field2;private String field3;private Date dateDoneLikeThis;/* setters and getters removed for brevity */@DoItWithAWhiffleBallBat(batType = WhiffleBallBat.BLACK_PLASTIC, shouldDoItWithAWhiffleBallBat = true)public void doWhateverItIs() {// method implementation}public void verifyIt() {// method implementation}}

带注释的二级

package com.keyhole.jonny.blog.annotations;import java.util.Date;@DoItLikeThis(action = "PROCESS", shouldDoItLikeThis = true, description = "Class used for annotation example.")
public class AnnotatedTwo implements AnnotatedClass {@DoItLikeThat(shouldDoItLikeThat = true)private String field1;@DoItLikeThat(shouldDoItLikeThat = true, roles = { "web", "client" })private String field2;private String field3;private Date dateDoneLikeThis;/* setters and getters removed for brevity */@DoItWithAWhiffleBallBat(shouldDoItWithAWhiffleBallBat = true)public void doWhateverItIs() {// method implementation}public void verifyIt() {// method implementation}}

处理注释

使用反射来处理注释实际上非常简单。 对于您可以为其创建和应用注释的每种元素类型,这些元素上都有一些使用注释的方法。 您需要做的第一件事是检查元素以确定是否有任何注释或检查该元素是否存在特定注释。

每个元素类型Class,Field和Method都实现了AnnotatedElement接口,该接口定义了以下方法:

  • getAnnotations() –返回此元素上存在的所有注释,包括所有继承的注释。
  • getDeclaredAnnotations() –仅返回直接存在于此元素上的注释。
  • getAnnotation(Class <A>注记类) –返回指定注解类型的元素注解,如果找不到,则返回null。
  • isAnnotation() –如果要检查的元素是注释,则返回true。
  • isAnnotationPresent(Class <?Extends Annotation>注解类) –如果所检查的元素上存在指定的注解,则返回true。

在处理批注时,我们要做的第一件事是检查批注是否存在。 为此,我们将对批注处理进行以下检查:

if (ac.getClass().isAnnotationPresent(DoItLikeThis.class)) {// process the annotation, "ac" being the instance of the object we are inspecting}

找到所需的批注后,我们将获取该批注并为该批注进行任何处理。 至此,我们将可以访问注释的元素及其值。 请注意,没有任何用于访问注释元素的获取器或设置器。

DoItLikeThis anno = ac.getClass().getAnnotation(DoItLikeThis.class);System.out.println("Action: " + anno.action());System.out.println("Description: " + anno.description());System.out.println("DoItLikeThis:" + anno.shouldDoItLikeThis());

对于字段和方法,检查当前注释会略有不同。 对于这些类型的元素,我们需要遍历所有字段或方法以确定元素上是否存在注释。 您将需要从Class中获取所有字段或方法,遍历Field或Method数组,然后确定元素上是否存在注释。 看起来应该像这样:

Field[] fields = ac.getClass().getDeclaredFields();for (Field field : fields) {if (field.isAnnotationPresent(DoItLikeThat.class)) {DoItLikeThat fAnno = field.getAnnotation(DoItLikeThat.class);System.out.println("Field: " + field.getName());System.out.println("DoItLikeThat:" + fAnno.shouldDoItLikeThat());for (String role : fAnno.roles()) {System.out.println("Role: " + role);}}}

结论

如您所见,创建自己的注释并进行处理非常简单。 在我提供的示例中,我们只是将元素的值输出到控制台或日志。 希望您能看到这些的潜在用途,并且将来可能会真正考虑创建自己的。 我在注释中看到的一些最佳用法是,它们替换一些配置代码或经常使用的通用代码,例如验证字段的值或将业务对象映射到Web表单。

最后,这是完整的源代码以及一个简单的Java主类来执行代码:

带注释的类处理器

package com.keyhole.jonny.blog.annotations;import java.lang.reflect.Field;
import java.lang.reflect.Method;public class AnnotatedClassProcessor {public void processClass(AnnotatedClass ac) {System.out.println("------Class Processing Begin---------");System.out.println("Class: " + ac.getClass().getName());if (ac.getClass().isAnnotationPresent(DoItLikeThis.class)) {// process the annotation, "ac" being the instance of the object we are inspectingDoItLikeThis anno = ac.getClass().getAnnotation(DoItLikeThis.class);System.out.println("Action: " + anno.action());System.out.println("Description: " + anno.description());System.out.println("DoItLikeThis:" + anno.shouldDoItLikeThis());System.out.println("------Field Processing---------");Field[] fields = ac.getClass().getDeclaredFields();for (Field field : fields) {if (field.isAnnotationPresent(DoItLikeThat.class)) {DoItLikeThat fAnno = field.getAnnotation(DoItLikeThat.class);System.out.println("Field: " + field.getName());System.out.println("DoItLikeThat:" + fAnno.shouldDoItLikeThat());for (String role : fAnno.roles()) {System.out.println("Role: " + role);}}}System.out.println("------Method Processing---------");Method[] methods = ac.getClass().getMethods();for (Method method : methods) {if ( method.isAnnotationPresent(DoItWithAWhiffleBallBat.class)) {DoItWithAWhiffleBallBat mAnno = method.getAnnotation(DoItWithAWhiffleBallBat.class);System.out.println("Use WhiffleBallBat? " + mAnno.shouldDoItWithAWhiffleBallBat());System.out.println("Which WhiffleBallBat? " + mAnno.batType());}}}System.out.println("------Class Processing End---------");}
}

运行处理器

package com.keyhole.jonny.blog.annotations;public class RunProcessor {/*** @param args*/public static void main(String[] args) {AnnotatedClassProcessor processor = new AnnotatedClassProcessor();processor.processClass(new AnnotatedOne());processor.processClass(new AnnotatedTwo());}}

翻译自: https://www.javacodegeeks.com/2014/09/processing-java-annotations-using-reflection.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/361794.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Excel 2007 Open XML文件结构(2)

Excel 2007 Open XML文件结构&#xff08;2&#xff09; 在以上文件中&#xff0c;根据<sheet>元素中r:id属性的值可得到工作表数据的XML文件。例如&#xff0c;在workbook.xml文件中名为工作表1的工作表的r:id属性为rld1&#xff0c;在以上文件中根据ID找到以下代码&…

Vue.js最佳实践

Vue.js最佳实践 第一招&#xff1a;化繁为简的Watchers 场景还原&#xff1a; created(){this.fetchPostList() },watch: {searchInputValue(){this.fetchPostList()} } 组件创建的时候我们获取一次列表&#xff0c;同时监听input框&#xff0c;每当发生变化的时候重新获取一…

Api demo源码学习(8)--App/Activity/QuickContactsDemo --获取系统联系人信息

本节通过Content Provider机制获取系统中的联系人信息&#xff0c;注意这个Anctivity直接继承的是ListActivity&#xff0c;所以不再需要setContentView函数来加载布局文件了&#xff08;我自己新建一个项目来跑这个anctivity时在这里卡了半天&#xff09;。 在AndroidManifest…

游戏大厅 从基础开始(6)--绕回来细说聊天室(中)之女仆编年史1

上一篇我们大致的了解了几种聊天室的行为模式 最简单明了的推模式 几乎不需要任何多余的语言来描述它的实现 这一篇我们看看如何实现拉模式更有效。 本图清晰的表现了"拉"模式聊天室的行为。 并发多用户向数据池写数据 并发多用户从数据池读书据 数据最好以时间为…

开发自上而下的Web服务项目

这是从Alessio Soldano编辑的Advanced JAX-WS Web Services手册中摘录的示例章节。 第一章介绍了自底向上创建Web服务端点的方法。 它允许非常快地将现有bean作为Web Service端点公开&#xff1a;在大多数情况下&#xff0c;将类转换为端点只需在代码中添加少量注释即可。 但…

React中ref的使用方法

React中ref的使用方法 在react典型的数据流中&#xff0c; props传递是父子组件交互的唯一方式&#xff1b;通过传递一个新的 props值来使子组件重新 re-render,从而达到父子组件通信。当然&#xff0c;就像react官网所描述的一样&#xff0c;在react典型的数据量之外&#xff…

mediawiki自动生成sitemap

Mediawiki 1.17.0提供了generateSitemap.php生成sitemap文件&#xff0c;可不必再使用扩展。 每次调用generateSitemap.php&#xff0c;生成全部sitemap。一般是通过定时任务(Linux下是cron)调用&#xff0c;定时生成。 generateSitemap.php命令示例&#xff1a; php /wiki/mai…

垃圾收集:提高吞吐量

这篇文章的灵感来自于在内存管理术语中的“ Pig in the Python ”定义。 显然&#xff0c;该术语用于解释GC反复促进大对象世代相传的情况。 据推测&#xff0c;这样做的效果类似于Python吞下整个猎物&#xff0c;只是在消化过程中被固定住了。 在接下来的24小时里&#xff0c…

Scss基础用法

Scss基础用法 一、注释用法&#xff1a; &#xff08;1&#xff09;//comment&#xff1a;该注释只是在.scss源文件中有&#xff0c;编译后的css文件中没有。 &#xff08;2&#xff09;/! /&#xff1a;重要注释&#xff0c;任何style的css文件中都会有&#xff0c;一般放置…

(Joomla)字符串截取

在用joomla进行开发的时候&#xff0c;需要用到国外的资源&#xff0c;一些module&#xff0c;组件&#xff0c;插件之类的&#xff0c;但是我们会发现&#xff0c;在字符串这个方法都需要进行修改。因为PHP的substr方法只是针对于非中文字符串有效&#xff0c;所以要使用另外一…

Pyechart:30分钟学会pyecharts数据可视化

30分钟学会pyecharts数据可视化 小红&#xff1a;你先跟我说说什么是pyecharts吧。 小明&#xff1a;Echarts 是一个由百度开源的数据可视化javascript库&#xff0c;凭借着良好的交互性&#xff0c;精巧的图表设计&#xff0c;得到了众多开发者的认可。而 Python 是一门富有表…

Spring @Configuration – RabbitMQ连接

我一直在转换必须使用Spring Configuration机制配置到RabbitMQ的连接的应用程序-最初&#xff0c;我使用xml bean定义文件来描述配置。 这是我的原始配置&#xff1a; <beans ...;><context:property-placeholder/><rabbit:connection-factory id"rabbit…

大叔手记(12):我的一次面试经历(谈大叔如何应对面试官)

本文目的 写本文的目的&#xff0c;大叔不是为了装逼&#xff08;虽然说话的口气有时候也确实有点装逼&#xff0c;性格导致的&#xff0c;咳。。。我得改&#xff09;&#xff0c;其实大叔在公司也只是小罗罗&#xff0c;本文的目的主要是为了向大家展示如何通过各种软技能应对…

欧拉回路判断规则

无向图&#xff1a;因为欧拉路径中&#xff0c;除了起点与终点以外&#xff0c;任意点的“进”“出”次数相等&#xff0c;所以除了两个点为奇点&#xff08;度数为奇数的点&#xff09;&#xff08;终点和起点&#xff09;以外&#xff0c;其它点的度数均为偶数。 如果是欧拉回…

使用Apache Camel 2.14的轻松REST端点

Apache Camel 最近发布了一个新版本 &#xff0c; 其中一些新功能由我的同事Claus Ibsen博客发布 。 您确实应该检查他的博客条目并深入研究更多细节&#xff0c;但是我希望尝试的功能之一是新的REST DSL 。 那么&#xff0c;这是什么新的DSL&#xff1f; 实际上&#xff0c;…

认识Mahout下的云计算机器学习

认识Mahout下的云计算机器学习 Apache Mahout 是 ApacheSoftware Foundation (ASF) 旗下的一个开源项目&#xff0c;提供一些可扩展的机器学习领域经典算法的实现&#xff0c;旨在帮助开发人员更加方便快捷地创建智能应用程序&#xff0c;并且&#xff0c;在 Mahout 的最近版本…

xshell常用的命令

Xshell查看所有的进程&#xff1a;ps -ef|grep tomcat查询该目录下所有的项目&#xff1a;lsXshell查看所有的zookeeper进程&#xff1a;ps -ef|grep zoo 进入到bin目录下 然后启动&#xff1a;./zkServer.sh startchmod命令大全及其解释 https://jingyan.baidu.com/article/5d…

NetBeans 8.0的五个新性能提示

NetBeans 8.0引入了几个新的Java提示 。 尽管有许多与Java Persistence API相关的新提示&#xff0c;但我还是关注Performance类别中的五个新提示。 NetBeans 8.0引入的五个新的“性能提示”是&#xff1a; 已装箱价值的装箱 冗余String.toString&#xff08;&#xff09; …

centos找不到IFCONFIG命令

# ifconfig  提示命令不存在  使用 # /sbin/ifconfig 即可  原因&#xff1a; 系统默认的环境变量设置不对  在 普通用户 和root用户下分别执行echo $PATH&#xff0c;PATH里少了四个地址&#xff1a;/sbin:/usr/sbin:/usr/local/sbin:/usr/kerberos/sbin  而&#x…

机智云小程序启蒙:WebSocket网页控制

机智云小程序启蒙&#xff1a;WebSocket网页控制 机智云Web版的JS远程控制设备&#xff0c;是调用了机智云开放的Open API和WebSocket API来实现的。这个是设计小程序最好的基础&#xff0c;也可以使无安卓设备的用户用网页远程控制设备。 其中&#xff0c;Open API用到的接口…