1.了解注解
我们有必要对JDK 5.0新增的注解(Annotation)技术进行简单的学习,因为Spring 支持@AspectJ,而@AspectJ本身就是基于JDK 5.0的注解技术。所以学习JDK 5.0的注解知识有助于我们更好地理解和掌握Spring的AOP技术。
对于Java开发人员来说,在编写代码时,除了源程序以外,我们还会使用 Javadoc标签对类、方法或成员变量进行注释,以便使用Javadoc工具生成和源代码配套的Javadoc文档。这些@param、@return 等Javadoc标签就是注解标签,它们为第三方工具提供了描述程序代码的注释信息。使用过Xdoclet的朋友,对此将更有感触,像Struts、 Hibernate都提供了Xdoclet标签,使用它们可以快速地生成对应程序代码的配置文件。
JDK5.0注解可以看成是Javadoc标签和Xdoclet标签的延伸和发展。在JDK5.0中,我们可以自定义这些标签,并通过Java语言的反射机制中获取类中标注的注解,完成特定的功能。
注解是代码的附属信息,它遵循一个基本原则:注解不能直接干扰程序代码的运行,无论增加或删除注解,代码都能够正常运行。Java语言解释器会忽略这些注解,而由第三方工具负责对注解进行处理。第三方工具可以利用代码中的注解间接控制程序代码的运行,它们通过Java反射机制读取注解的信息,并根据这些信息更改目标程序的逻辑,而这正是Spring
AOP对@AspectJ提供支持所采取的方法。
注解的语法比较简单,除了@符号的使用以外,它基本上与java的固有语法一致,java内置了三种注解,定义在java.lang包中。
@Override:只能用在方法之上的,用来告诉别人这一个方法是改写父类的。
@Deprecated:建议别人不要使用旧的API的时候用的,编译的时候会用产生警告信息,可以设定在程序里的所有的元素上。
@SuppressWarnings:表示关闭一些不当的编译器警告信息。
2.定义注解
下面是一个定义注解的实例。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface Description {
String value();
}
其中的@interface是一个关键字,在设计annotations的时候必须把一个类型定义为@interface,而不能用class或interface关键字。所有的注解类都隐式继承于 java.lang.annotation.Annotation,注解不允许显式继承于其他的接口。
一个注解可以拥有多个成员,成员声明和接口方法声明类似,这里,我们仅定义了一个成员,成员的声明有以下几点限制:
a)成员以无入参无抛出异常的方式声明,如boolean value(String str)、boolean value() throws Exception等方式是非法的;
b)可以通过default为成员指定一个默认值,如String level() default "LOW_LEVEL"、int high() default 2是合法的,当然也可以不指定默认值;
c)成员类型是受限的,合法的类型包括原始类型及其封装类、String、Class、enums、注解类型,以及上述类型的数组类型。如ForumService value()、List foo()是非法的。
d)如果注解只有一个成员,则成员名必须取名为value(),在使用时可以忽略成员名和赋值号(=),如@Description("使用注解的实例")。注解类拥有多个成员时,如果仅对value成员进行赋值则也可不使用赋值号,如果同时对多个成员进行赋值,则必须使用赋值号,如@DeclareParents
(value = "NaiveWaiter", defaultImpl = SmartSeller.class)。
e)注解类可以没有成员,没有成员的注解称为标识注解,解释程序以标识注解存在与否进行相应的处理;
注解定义包含四个元注解,分别为@Target,@Retention,@Documented,@Inherited。各元注解的作用如下:
1)@Target
表示该注解用于什么地方,可能的ElemenetType参数包括:
ØElemenetType.CONSTRUCTOR构造器声明。
ØElemenetType.FIELD域声明(包括enum实例)。
ØElemenetType.LOCAL_VARIABLE局部变量声明。
ØElemenetType.METHOD方法声明。
ØElemenetType.PACKAGE包声明。
ØElemenetType.PARAMETER参数声明。
ØElemenetType.TYPE类,接口(包括注解类型)或enum声明。
2)@Retention
表示在什么级别保存该注解信息。可选的RetentionPolicy参数包括:
ØRetentionPolicy.SOURCE注解将被编译器丢弃。
ØRetentionPolicy.CLASS注解在class文件中可用,但会被VM丢弃。
ØRetentionPolicy.RUNTIMEVM将在运行期也保留注释,因此可以通过反射机制读取注解的信息。
举一个例子,如@Override里面的Retention设为SOURCE,编译成功了就不要这一些检查的信息,相反,@Deprecated里面的Retention设为RUNTIME,表示除了在编译时会警告我们使用了哪个被 Deprecated的方法,在执行的时候也可以查出该方法是否被Deprecated。
3)@Documented
将此注解包含在javadoc中
4)@Inherited
允许子类继承父类中的注解
3.使用注解
下面是一个使用注解注解的实例。
@Description(value="使用注解的实例")
public class TestAnnotation {
}
使用注解的语法:@<注解名>(<成员名1>=<成员值1>,<成员名1>=<成员值1>,...)
如果成员是数组类型,可以通过{}进行赋值,如boolean数组的成员可以设置为{true,false,true}。下面是几个注解标注的例子:
1)多成员的注解
@AnnoExample(id=2868724,synopsis="Enabletime-travel", engineer="Mr.Peabody")
2)一个成员的注解,成员名为value
可以省略成员名和赋值符号:@Copyright("RightReserved")
@Copyright("2011 bookegou.com All Right Reserved")
3)无成员的注解
@Override
@Override
4)成员为字符串数组的注解
@SuppressWarnings(value={"unchecked","fallthrough"})
@SuppressWarnings(value={"unchecked","fallthrough"})
5)成员为注解数组类型的注解
@Reviews({@Review(grade=Review.Grade.EXCELLENT,reviewer="df"),
@Review(grade=Review.Grade.UNSATISFACTORY,reviewer="eg",
comment="Thismethodneedsan@Overrideannotation")})
@Reviews({@Review(grade=Review.Grade.EXCELLENT,reviewer="df"),
@Review(grade=Review.Grade.UNSATISFACTORY,reviewer="eg",
comment="This method needs an @Override annotation")})
@Reviews注解拥有一个@Review注解数组类型的成员,@Review注解类型有三个成员,其中reviewer、comment都是String类型,但comment有默认值,grade是枚举类型的成员。
4.解析注解
下面是一个解析注解的实例。
public class ParseAnnotation {
public static void main(String[] args) throws Exception{
final Class cls = Class.forName("com.annotation.TestAnnotation");
final Method[] method = cls.getMethods();
// 判断是否有指定注解类型的注解
if(cls.isAnnotationPresent(Description.class)) {
// 根据注解类型返回指定类型的注解
Description des = (Description)cls.getAnnotation(Description.class);
System.out.println("注解描述:" + des.value());
}
}
}
输出结果如下:
注解描述:使用注解的实例
前面提到过,注解不会直接影响程序的运行,但是第三方程序或工具可以利用代码中的注解完成特殊的任务,间接控制程序的运行。对于RetentionPolicy.RUNTIME保留期限的注解,我们可以通过反射机制访问类中的注解。
在JDK5.0里,Package、Class、Constructor、 Method以及Field等反射对象都新增了访问注解信息的方法:<T extends Annotation>T getAnnotation(Class<T> annotationClass),该方法支持通过泛型直接返回注解对象。
分享到:
相关推荐
全面解析java注解PPT课件.pptx
全面解析java注解PPT学习教案.pptx
一个自定义java注解,与注解解析的demo.
主要介绍了java注解的全面分析的相关资料,Java提供的一种原程序中的元素关联任何信息和任何元数据的途径和方法,需要的朋友可以参考下
主要介绍了Java中的注解与注释,简单来说注解以@符号开头而注释被包含在/***/符号中,各自具体的作用则来看本文详解,需要的朋友可以参考下
统一采用全路径请求,URL格式: 1> basePath/web/moduleName/*_ *.action {1} EntityName,{2} ActionMethodName 2> basePath/web/moduleName/gotoXxx.action (无需调用Service,直接跳转) 包括jQuery的Ajax...
Java虚拟机规范(Java SE 8版)》完整而准确地阐释了Java虚拟机各方面的细节,围绕Java虚拟机整体架构、编译器、class文件格式、加载、链接与初始化、指令集等核心主题对Java虚拟机进行全面而深入的分析,深刻揭示...
JavaIO 流全解析 深入理解 Java 多线程 Java 网络编程 手动开发一个 Web 服务器 深入理解 Java 注解+反射 Java23 种设计模式 学会 Java 正则表达式 JDBC 详解 Java 数据结构和算法 深入理解 Java 虚拟机 ...
本书完整而准确地阐释了Java虚拟机各方面的细节,围绕.Java虚拟机整体架构、编译器、class文件格式、加载、链接与初始化、指令集等核心主题对Java虚拟机进行全面而深入的分析,深刻揭示Java虚拟机的工作原理。...
Java SE 8版-带目录-pdf,本书完整而准确地阐释了Java虚拟机各方面的细节,围绕Java虚拟机整体架构、编译器、class文件格式、加载、链接与初始化、指令集等核心主题对Java虚拟机进行全面而深入的分析,深刻揭示Java...
parboiled 是一个纯Java库提供了一种轻量级,易于使用,功能强大和优雅的PEG(解析表达式语法)分析设施。你定义的Java源代码的语法规则,直接,没有必要专门编写和维护,外部语法文件。同时保持蒸提供全面的支持,...
《Java虚拟机规范(Java SE 8版)英文版》全面而准确地阐释了Java虚拟机各方面的细节,围绕Java虚拟机整体架构、编译器、class文件格式、加载、链接与初始化、指令集等核心主题对Java虚拟机进行全面而深入的分析,...
《Java虚拟机规范(Java SE 8版)英文版》全面而准确地阐释了Java虚拟机各方面的细节,围绕Java虚拟机整体架构、编译器、class文件格式、加载、链接与初始化、指令集等核心主题对Java虚拟机进行全面而深入的分析,...
Java局域网通信——飞鸽传书源代码,大家都知道VB版、VC版还有Delphi版的飞鸽传书软件,但是Java版的确实不多,因此这个Java文件传输实例不可错过,Java网络编程技能的提升很有帮助。 Java聊天程序,包括服务端和...
Java 源码包 Applet钢琴模拟程序java源码 2个目标文件,提供基本的音乐编辑功能。编辑音乐软件的朋友,这款实例会对你有所帮助。 Calendar万年历 1个目标文件 EJB 模拟银行ATM流程及操作源代码 6个目标文件,EJB来...
parboiled 是一个纯Java库提供了一种轻量级,易于使用,功能强大和优雅的PEG(解析表达式语法)分析设施。你定义的Java源代码的语法规则,直接,没有必要专门编写和维护,外部语法文件。同时保持蒸提供全面的支持,...
parboiled 是一个纯Java库提供了一种轻量级,易于使用,功能强大和优雅的PEG(解析表达式语法)分析设施。你定义的Java源代码的语法规则,直接,没有必要专门编写和维护,外部语法文件。同时保持蒸提供全面的支持,...
parboiled 是一个纯Java库提供了一种轻量级,易于使用,功能强大和优雅的PEG(解析表达式语法)分析设施。你定义的Java源代码的语法规则,直接,没有必要专门编写和维护,外部语法文件。同时保持蒸提供全面的支持,...
parboiled 是一个纯Java库提供了一种轻量级,易于使用,功能强大和优雅的PEG(解析表达式语法)分析设施。你定义的Java源代码的语法规则,直接,没有必要专门编写和维护,外部语法文件。同时保持蒸提供全面的支持,...