在Java中注解是很重要的一个组成部分,它是从J2SE 5.0开始就存在的。我们在日常开发的应用中应该已经见过类似于@Override@Deprecated注解。在这篇文章中,我讨论注解是什么,为什么他们会存在,他们如何起作用,如何自定义注解(有代码示例),注解的有效使用场景,最后会说注解和ADF。这将是一个很长的帖子,所以拿一些咖啡,准备潜入注解的世界。

1. 注解是什么?

用一个单词来解释注解的概念,那就是metadatametadata是关于数据的数据。因此注解是代码的元数据。例如,看一下下面的代码片段:

@Override
public String toString() {return "This is String Representation of current object.";
}

我重写了toString()方法,并且在代码上面使用了@Override注解。即使我不加@Override注解,代码也可以正常运行部存在任何问题。所以加该注解的优点和该注解代表的含义是什么?@Override注解告诉编译器该方法是一个被重写的方法(有关方法的metadata)。如果父类中不存在任何此类方法,则抛出编译器错误(方法不会覆盖其父类中的方法)。现在,如果我犯一个排版的错误,并且使用方法名字如 toStrring() {double r},并且没有使用@Override注解,我们代码可以成功变异和执行,但是它的输出与我的预期结果不是一致的。所以现在,我们理解注解是什么,但仍然,阅读正式定义是好的。

注解是一种特殊的Java构造,用于修饰类,方法,字段,参数,变量,构造函数或包。
它是JSR-175选择提供元数据的工具。

2. 为什么要引入注解?

在注解之前(甚至之后),XML被广泛用于metadata,并且不知何故,一组特定的应用程序开发人员和架构师认为XML维护变得很麻烦。他们想要的东西可以与代码紧密结合,而不是XML,它与代码非常松散耦合(在某些情况下,几乎是分开的)。如果你谷歌XML与注解,你会发现很多有趣的辩论。一个有趣的观点是,引入了XML配置来将配置与代码分开。最后两个陈述可能会在你的脑海中产生一些怀疑,这两个是创建一个循环,但两者都有其优点和缺点。让我们试着用一个例子来理解。

假设您要设置一些应用程序范围的常量/参数。在这种情况下,XML将是更好的选择,因为这与任何特定的代码片段无关。如果要将某个方法公开为服务,则注解将是更好的选择,因为它需要与该方法紧密耦合,并且方法的开发人员必须意识到这一点。

另一个重要因素是注解定义了在代码中定义元数据的标准方法。在注解之前,人们还使用自己的方式来定义元数据。一些示例使用标记接口,注解,transient关键字等。每个开发人员都需要以自己的方式来决定元数据,但是注解是的东西标准化。

目前,大多数框架都使用XMLAnnotations的组合来利用两者的积极方面。

3. 注解如何起作用以及如何自定义注解

在开始此解释之前,我建议您下载此示例代码AnnotationsSample.zip,并在您选择的任何IDE中保持开放,因为它将帮助您更好地理解以下解释。

编写注解非常简单。您可以将注解定义与接口定义进行比较。让我们看两个例子,一个是标准的@Override注解,一个是@Todo的自定义注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)public @interface Override {}

@Override似乎有点可疑;它没有做任何事情 ,它只是检查是否在父类中定义了一个方法。
好吧,不要惊讶;我不是在开玩笑。@Override注解的定义只包含那么多代码。
这是要理解的最重要的部分,我正在重申:注解只是metadata,不包含任何业务逻辑

艰难消化但真实。如果注释不包含逻辑,那么其他人必须做某事并且某人是此注解metadata的使用者。注解仅提供有关定义它的属性(类/方法/包/字段)的信息。使用者是一段代码,它读取此信息然后执行必要的逻辑。

当我们讨论像@Override这样的标准注解时,JVM就是消费者,它在字节码级别起作用。
这是应用程序开发人员无法控制的东西,也不能用于自定义注解。所以我们需要为我们的注解写消费者。

让我们逐一理解用于编写注解的关键术语。在上面的示例中,您将看到注解用于注解。

当写自定义注解的时候J2SE 5.0java.lang.annotation包中提供了四种注解可以被使用:

  • @Documented:是否将注解放在Javadocs
  • @Retention:当需要注解的时候
  • @Target:注解作用的位置
  • @Inherited: 子类是否获得注解

@Documented:一个简单的市场注解,告诉您是否在Java文档中添加注解。

@Retention :定义注解应保留多长时间。

  • RetentionPolicy.SOURCE: 在编译期间丢弃。编译完成后,这些注解没有任何意义,因此它们不会写入字节码。示例:@Override@ SuppressWarnings
  • RetentionPolicy.CLASS: 在类加载期间丢弃。在进行字节码级后处理时很有用。这是默认值。
  • RetentionPolicy.RUNTIME: 不会丢弃。注解应该可以在运行时进行反射。这是我们通常用于自定义注解的内容。

@Target: 可以放置注解的位置。如果不指定,则可以将注解放在任何位置。以下是有效值。
这里的一个重点是它只是包容性,这意味着如果你想要对7个属性进行注解并且只想要只排除一个属性,则需要在定义目标时包括所有7个。

  • ElementType.TYPE (class, interface, enum)

  • ElementType.FIELD (instance variable)

  • ElementType.METHOD

  • ElementType.PARAMETER

  • ElementType.CONSTRUCTOR

  • ElementType.LOCAL_VARIABLE

  • ElementType.ANNOTATION_TYPE (on another annotation)

  • ElementType.PACKAGE (remember package-info.java)

@Inherited: 控制注解是否应该影响子类。

现在,注解定义中的内容是什么?注解仅支持基本数据类型,字符串和枚举。注解的所有属性都定义为方法,也可以提供默认值。


@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface
Todo {public enum Priority {LOW, MEDIUM, HIGH}public enum Status {STARTED, NOT_STARTED}String author() default "Yash";Priority priority() default Priority.LOW;Status status() default Status.NOT_STARTED;
}

以下是如何使用上述注解的示例:


@Todo(priority = Todo.Priority.MEDIUM, author = "Yashwant", status = Todo.Status.STARTED)
public void incompleteMethod1() {//Some business logic is written//But it’s not complete yet
}

如果注释中只有一个属性,则应将其命名为value,并且在使用时可以在没有属性名称的情况下使用它。

@interface Author{String value();
}
@Author("Yashwant")public void someMethod() {}

到现在为止还挺好。我们定义了自定义注解并将其应用于某些业务逻辑方法。现在,是时候写一个消费者了。为此,我们需要使用反射。如果您熟悉反射代码,您就知道反射提供了ClassMethodField对象。所有这些都有一个getAnnotation()方法,它返回注解对象。我们需要将此对象转换为自定义注解(在使用instanceOf()检查之后),然后,我们可以调用自定义注解中定义的方法。
让我们看一下使用上面注解的示例代码:

Class businessLogicClass = BusinessLogic.class;
for(Method method : businessLogicClass.getMethods()) {Todo todoAnnotation = (Todo)method.getAnnotation(Todo.class);if(todoAnnotation != null) {System.out.println(" Method Name : " + method.getName());System.out.println(" Author : " + todoAnnotation.author());System.out.println(" Priority : " + todoAnnotation.priority());System.out.println(" Status : " + todoAnnotation.status());}
}

用例注解

注解非常强大,SpringHibernate等框架非常广泛地使用注解进行日志记录和验证。
注解可以在使用标记接口的位置使用。标记接口适用于完整的类,但您可以定义可以在单个方法上使用的注解,例如,某个方法是否作为服务方法公开。

servlet规范3.0中,引入了许多注解,尤其是与servlet安全性相关的注解。我们来看看几个:

  • HandlesTypes - 用于声明传递给ServletContainerInitializer的应用程序类数组。
  • HttpConstraint - 此注解表示应用于具有HTTP协议方法类型的所有请求的安全性约束,这些类型在ServletSecurity注解中未由相应的HttpMethodConstraint表示。
  • HttpMethodConstraint - 特定的安全性约束可以应用于不同类型的请求,通过在ServletSecurity注解内使用此注解来区分HTTP协议方法类型。
  • MultipartConfig - 此注解用于指示声明它的Servlet期望使用multipart / form-data MIME类型进行请求。
  • ServletSecurity - 在Servlet实现类上声明此注解,以强制对HTTP协议请求进行安全性约束。
  • WebFilter - 用于声明Servlet过滤器的注解。
  • WebInitParam - 用于在WebFilterWebServlet注解内的ServletFilter上声明初始化参数的注解。
  • WebListener - 用于在给定Web应用程序上下文中为各种类型的事件声明侦听器的注解。
  • WebServlet- 此注解用于声明Servlet的配置。

ADF(应用程序开发框架)和注解

现在,我们在讨论的最后部分:应用程序开发框架,也称为ADFADFOracle开发,用于构建Oracle融合应用程序。我们已经看到了优点和缺点,我们知道如何编写自定义注解,但我们可以在ADF中哪里使用自定义注解? ADF是否提供任何本地注解?

这些肯定是有趣的问题:但是否有某些限制阻止在ADF中大规模使用注解?前面提到的框架,如SpringHibernate,使用AOP(面向方面编程)。在AOP中,框架提供了一种为任何事件注入预处理和后处理代码的机制。例如,您有一个钩子来在方法执行之前和之后放置代码,因此您可以在这些位置编写您的使用者代码。 ADF不使用AOP。如果我们有任何有效的注解用例,我们可能需要通过继承方式。

希望你喜欢这篇文章。请在评论中放下你的想法!

原文链接:https://dzone.com/videos/devnexus2015/how-annotations-work-java

作者:Yashwant Golecha

译者:lee

Java中的注解是如何起作用的相关推荐

  1. java中注解的解析_全面解析Java中的注解与注释

    注解一.什么是 Annotation? (注解 or 注释)Annotation, 准确的翻译应该是 -- 注解. 和注释的作用完全不一样. Annotation 是JDK5.0及以后版本引入的一个特 ...

  2. 深入理解JAVA中的注解

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

  3. java里什么是注释,全面解析Java中的注解与注释

    注解 一.什么是 Annotation? (注解 or 注释) Annotation, 准确的翻译应该是 -- 注解. 和注释的作用完全不一样. Annotation 是JDK5.0及以后版本引入的一 ...

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

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

  5. Java中自定义注解的使用

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

  6. java注释_全面解析Java中的注解与注释

    注解一.什么是 Annotation? (注解 or 注释)Annotation, 准确的翻译应该是 -- 注解. 和注释的作用完全不一样. Annotation 是JDK5.0及以后版本引入的一个特 ...

  7. java中的注解(二)

    今天我继续来介绍java中的注解.注解与接口和类不同的是注解是不允许继承的,但是注解中有一个和继承有关的元注解:@Inherited.如果我们在定义注解时候加上这个元注解那么我们就可以在子类中监测到该 ...

  8. 详解Java中的注解

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

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

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

最新文章

  1. 程序人生系列谈:《程序员》带给我的启发故事
  2. Ubuntu 使用国内apt源
  3. spring用xml还是java_Spring中如何混用XML与Java装配方式
  4. PPDE英雄帖!广邀全球开发者执开源之桨,汇百川成海
  5. 如何用python画组合图形_python_matplotlib画组合图
  6. C# 中的可变参数方法(VarArgs)
  7. Python最常用的函数、基础语句有哪些?你都知道吗
  8. php怎么构造一个验证码,PHP封装一个生成验证码的函数
  9. linux 的FAQ
  10. ConcurrentLinkedQueue源码
  11. OpenGL基础43:抗锯齿
  12. multimap多重关联容器
  13. jQuery Mobile中选择select的data-*选项
  14. cdr圆形渐变填充怎么设置_适用于平面设计的软件cdr!
  15. Python os.popen() 方法
  16. 魔兽各服务器位置,魔兽世界怀旧服矿点分布在哪 全地图采矿位置一览(多图)
  17. 文学-赋:洛神赋(三国曹植赋作)
  18. 基于STM32f407的TSL2561模块的使用
  19. GIVE 添加 bigWig 文件
  20. mysql查询所有男生中姓王的_MySQL的查询练习

热门文章

  1. Linux 中断原理之软中断
  2. TCP连接断开原理剖析
  3. 2020年网络安全等级保护执法典型案例汇总(截至2020年3月26日)
  4. Bresenham画线算法的推导
  5. 域用户如何批量修改服务器时间,如何批量修改word中的域
  6. 智合同丨智能合同审查·赋能合同智能应用
  7. Latex bibtex制作参考文献遇到问题总结
  8. 第十八届中国国际人才交流大会云端开幕,VR虚拟展厅邀你“云逛展”
  9. wave6000可以c语言编程吗,WAVE6000使用教程初步.doc
  10. 爱数oracle rac备份,客户案例 |爱数AnyStorage打造宁乡县人民医院RAC+虚拟化混合架构容灾...