志在指尖
用双手敲打未来

注解在Java中是如何工作的?

注解不断是Java的一个十分重要的局部,它从J2SE5.0开端就曾经存在了。在我们的应用程序代码中,经常看到@Override和@Deprecated这样的注解。在本文中,我将讨论注解到底是什么,为什么引入注解,它们是如何工作的,如何编写自定义注解(有示例代码),注解的有效场景是什么,最后是注解和ADF。这将是一个很长的帖子,所以来一点咖啡,准备好进入注解的世界。
1.注解是什么?
用一个词来能够解释:注解即是元数据。元数据是关于数据的数据。所以注解是代码的元数据。举个例子,查看下面的代码。
@Override
publicStringtoString(){
return”ThisisStringRepresentationofcurrentobject.”;
}
我在以上代码中重写toString()办法时运用了@Override注解。即便我不运用@Override,代码依然可以正常工作,没有任何问题。那么,这个注解的优点是什么?又代表了什么?@Override通知编译器,此办法是一个重写的办法(有关该办法的元数据),假如父类中不存在此类办法,则引发编译器错误(超类中没有被掩盖其的办法)。如今,假如我犯了一个排版错误,并运用办法名为toStrring(){doubler}假如我没有运用@Override,我的代码会胜利地编译和执行,但是结果将会与预期不同。如今,我们了解了注解是什么,阅读正式的定义是很有用途的。
注解是一种特殊的Java结构,用于修饰类、办法、字段、参数、变量、结构函数或包。这是JSR-175选择的提供元数据的工具。Java
2.为什么引入注解?
在注解呈现之前(以至之后),XML被普遍地用于元数据,但是,一局部特定的应用程序开发人员和架构师以为XML维护变得费事了。他们希望可以经过某种方式与代码严密耦合,来替代XML,由于XML与代码十分松懈地耦合(在某些状况下,简直是独立的)。假如你在谷歌上搜索“XMLvsannotations”,你会发现很多有趣的争论。有趣的一点是,XML配置是为了将配置从代码中别离出来而引入的。最后两种说法可能会在你的脑海中产生一些疑问,即这两种说法都在发明一个循环,但两者各有优缺陷。让我们试着用一个例子来了解。
假定您希望设置一些应用程序范围的常量/参数。在这个场景中,XML将是一个更好的选择,由于这与任何特定的代码段无关。假如您希望将某些办法公开为效劳,那么注解将是一个更好的选择,由于它需求与该办法严密耦合,并且该办法的开发人员必需晓得这一点。
另一个重要要素是注解定义了在代码中定义元数据的规范办法。在注解之前,人们还运用本人的办法来定义元数据。一些例子是运用标志接口、注解、暂时关键字等。每个开发人员都需求依据本人的方式来决议元数据,但是注解是规范化的东西。
往常,大多数框架都将XML和注解分离起来,充沛应用两者的优点。
3.注解如何工作以及如何编写自定义注解
在开端解释之前,我倡议您下载这个注释(AnnotationsSample.zip)的示例代码,并在您常用的IDE中坚持翻开,由于它将协助您更好天文解下面的解释。
编写注解十分简单。您能够将注解定义与接口定义停止比拟。让我们看两个例子—一个是规范@Override第二个注解是自定义注解。@Todo:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public@interfaceOverride{
}
似乎有些可疑之处@Override它没有做任何事情—它只是检查能否在父类中定义了一个办法。别诧异,我不是在开玩笑。重写注解的定义只要那么多代码。这是需求了解的最重要的局部,我重申一遍:注解只是元数据,不包含任何业务逻辑。很难了解但却是真的。假如注解不包含逻辑,那么一定有人在做一些事情,并且有人是这个注解元数据的消费者。注解只提供有关定义的属性(类/办法/包/字段)的信息。消费者是一段代码,它读取这些信息,然后执行必要的逻辑。
当我们议论规范注解时,比方@Override,JVM是运用者,它是在字节码级别工作的。这是应用程序开发人员无法控制、也不能用于自定义注解的东西。因而,我们需求为我们本人的注解写一些消费实例。
让我们逐一了解用于编写注解的关键术语。在上面的例子中,您将看到注解如何被应用。
J2SE5.0在java.lang.annotation包中提供了四个注解,它们仅在编写注解时运用:
@Documented–能否将注解放在Javadocs中
@Retention–注解什么时分被保存
@Target?–注解能够运用的中央
@Inherited–子类能否能够继承注解。
@Documented-一个简单的标志注解,它标识了能否将注解添加到Javadoc中。
@Retention-定义应保存注解的时间。
RetentionPolicy.SOURCE在编译期间丢弃。这些注解在编译完成后没有任何意义,因而它们不会被写入字节码。例子:@Override,@SuppressWarnings
RetentionPolicy.CLASS–在类加载期间丢弃。应用在停止字节码级别的编译期间。有些令人诧异的是,这是默许的。
RetentionPolicy.RUNTIME–不会丢弃。该注解能够在运转时停止反射。这是我们通常用于自定义注解的内容。
@Target-注解能够运用的中央。假如不指定这一属性,注解能够应用在任何中央。以下是该注解的有效值。这里的一个要点,它只要包含的方式,这意味着假如您想要对7个属性停止注解,并且只想扫除一个属性,这时需求在定义目的时包含一切7个属性。
ElementType.TYPE(类,接口,枚举)
ElementType.FIELD(实例变量)
ElementType.METHOD
ElementType.PARAMETER
ElementType.CONSTRUCTOR
ElementType.LOCAL_VARIABLE
ElementType.ANNOTATION_TYPE(用于其他注解)
ElementType.PACKAGE(记住package-info.java)
@Inherited-控制注解能否应该影响子类。
如今,注解定义中包含了什么?注解只支持根本类型、字符串和枚举。注解的一切属性都定义为办法,并且还能够提供默许值。
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interfaceTodo{
publicenumPriority{LOW,MEDIUM,HIGH}
publicenumStatus{STARTED,NOT_STARTED}
Stringauthor()default”Yash”;
Prioritypriority()defaultPriority.LOW;
Statusstatus()defaultStatus.NOT_STARTED;
}
以下是如何运用上述注解的示例:
@Todo(priority=Todo.Priority.MEDIUM,author=”Yashwant”,status=Todo.Status.STARTED)
publicvoidincompleteMethod1(){
//Somebusinesslogiciswritten
//Butit’snotcompleteyet
}
假如注解中只要一个属性,则应该将其命名为“value”,并且能够在运用时不运用属性称号。
@interfaceAuthor{
Stringvalue();
}
@Author(“Yashwant”)
publicvoidsomeMethod(){
}
目前为止一切顺利。我们曾经定义了自定义注解,并将其应用于一些业务逻辑办法。如今,是时分写一个消费的实例了。为了完成这个目的,我们需求运用到反射。假如您熟习反射代码,那么您就晓得反射提供了类、办法和字段对象。一切这些对象都有一个getAnnotation()办法,该办法返回注解对象。我们需求将此对象转换为自定义注解(在运用instanceOf()检查之后),然后,我们能够调用自定义注解中定义的办法。让我们看一下示例代码,它运用了上面的注解:
ClassbusinessLogicClass=BusinessLogic.class;
for(Methodmethod:businessLogicClass.getMethods()){
TodotodoAnnotation=(Todo)method.getAnnotation(Todo.class);
if(todoAnnotation!=null){
System.out.println(“MethodName:”+method.getName());
System.out.println(“Author:”+todoAnnotation.author());
System.out.println(“Priority:”+todoAnnotation.priority());
System.out.println(“Status:”+todoAnnotation.status());
}
}
4.注解用例
注解十分的强大,Spring和Hibernate等框架十分普遍地运用注解停止日志记载和考证。注解能够在运用标志接口的中央运用。标志接口用于整个类,但您能够定义能够用于单个办法的注解,例如,某个办法能否公开为效劳办法。
在servlet3.0标准中,引入了许多注解,特别是与servlet平安有关的注解。我们先来看看几个:
HandlesTypes-此注解用于声明传送给ServletContainerInitializer的应用程序类数组。
HttpConstraint-此注解表示应用于一切具有HTTP协议办法类型的恳求的平安约束,在ServletSecurity上没有相应的HttpMethodConstraint注解时。
HttpMethodConstraint-特定的平安约束能够应用于不同类型的恳求,在ServletSecurity上注解。
MultipartConfig-此注解用于指示声明它的servlet将运用multiPart/form-DataMIME类型发出恳求。
ServletSecurity-在servlet完成类上声明此注解,对HTTP协议恳求执行平安约束。
WebFilter-用于声明servlet过滤器的注解。
WebInitParam-用于在servlet或过滤器上声明初始化参数的注解,在WebFilter或WebServlet上注解。
WebListener-用于在给定的Web应用程序上下文中声明各品种型事情的侦听器的注解。
WebServlet-此注解用于声明servlet的配置。
5.应用程序开发框架(ADF,ApplicationDevelopmentFramework)和注解
如今,我们正在讨论的最后一局部:应用程序开发框架(ADF)。ADF由Oracle开发,用于构建Oracle交融应用程序。我们曾经看到了优点和缺陷,并且晓得如何编写自定义注解,但是在ADF中我们能够在哪里运用自定义注解呢?ADF能否提供本地注解?
这些无疑是有趣的问题:但是能否存在某些限制来阻止在ADF中大范围运用注解?前面提到的框架(如Spring和Hibernate)运用的AOP(面向方面的编程)。在AOP中,框架提供了为任何事情的预处置和后处置注入代码的机制。例如,您有一个钩子在办法执行之前和之后放置代码,因而您能够在这些中央编写自定义代码。ADF不运用AOP。假如我们有任何有效的注解用例,我们可能需求经过继承方式。

未经允许不得转载:IT技术网站 » 注解在Java中是如何工作的?
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!

 

志在指尖 用双手敲打未来

登录/注册IT技术大全

热门IT技术

C#基础入门   SQL server数据库   系统SEO学习教程   WordPress小技巧   WordPress插件   脚本与源码下载