自定义Annotation spring annotation

使用过spring框架,ejb框架,cxf,junit2等支持Annotation技术的框架的人都会很清楚,其中除了jdk自带的一些Annotation以外,我们还可以自己定义很多Annotation帮助我们进行框架的搭建
一:Quick Start
定义Annotation的时候和定义接口的方式很类似,只不过再interface前面加了@
Java代码
  1. packagecom.wangwenjun.annatation.userdefined;
  2. public@interfaceUserdefinedAnnotation{
  3. }
package com.wangwenjun.annatation.userdefined;public @interface UserdefinedAnnotation {        }
代码很简单,没有任何的结构,只是一个空的Annotation,接下来演示一下如何对其进行使用。
Java代码
  1. packagecom.wangwenjun.annatation.userdefined;
  2. publicclassUseAnnotation{
  3. @UserdefinedAnnotation
  4. publicstaticvoidmain(String[]args){
  5. System.out.println("hello");
  6. }
  7. }
package com.wangwenjun.annatation.userdefined;public class UseAnnotation {                @UserdefinedAnnotation        public static void main(String[] args) {                System.out.println("hello");        }}
上述的代码简单到再也不能简单,甚至简单到说明不了任何问题,只是从它上面可以看得出来我们如何自定一个Annotation,并且如何的使用它,我们并没有给自定义Annotation中添加任何的属性,甚至没有指定其保持力(Retention),可继承性(Inherited),标注对象(Target)等
二:Annotation属性值
Annotation属性值大致有以下三种:
● 基本类型
● 数组类型
● 枚举类型
我们在下面的文字中将会一个个的进行演示和说明。
1:基本串类型
Java代码
  1. packagecom.wangwenjun.annatation.userdefined;
  2. public@interfaceUserdefinedAnnotation{
  3. intvalue();
  4. Stringname();
  5. Stringaddress();
  6. }
package com.wangwenjun.annatation.userdefined;public @interface UserdefinedAnnotation {        int value();        String name();        String address();}
上面是一个自定义的annotation,可能稍微有一些复杂,只不过是为了更多的说明一下问题,可以看出来在定义属性的时候有点像interface定义方法一样,每一个属性名称之后需要加上括号,接下来看看如何使用。
Java代码
  1. packagecom.wangwenjun.annatation.userdefined;
  2. publicclassUseAnnotation{
  3. @UserdefinedAnnotation(value=123,name="wangwenjun",address="火星")
  4. publicstaticvoidmain(String[]args){
  5. System.out.println("hello");
  6. }
  7. }
package com.wangwenjun.annatation.userdefined;public class UseAnnotation {        @UserdefinedAnnotation(value=123,name="wangwenjun",address="火星")        public static void main(String[] args) {                System.out.println("hello");        }}
如果在使用UserdefinedAnnotation时候不给相关的属性赋值,会出现错误。
需要说明的一点事如果一个annotation中只有一个属性名字叫value,我没在使用的时候可以给出属性名也可以省略。
Java代码
  1. public@interfaceUserdefinedAnnotation{
  2. intvalue();
  3. }
  4. packagecom.wangwenjun.annatation.userdefined;
  5. publicclassUseAnnotation{
  6. @UserdefinedAnnotation(value=123)
  7. publicstaticvoidmain(String[]args){
  8. System.out.println("hello");
  9. }
  10. }
public @interface UserdefinedAnnotation {        int value();}package com.wangwenjun.annatation.userdefined;public class UseAnnotation {                @UserdefinedAnnotation(value=123)        public static void main(String[] args) {                System.out.println("hello");        }}
也可以写成如下的形式
Java代码
  1. @UserdefinedAnnotation(123)
  2. publicstaticvoidmain(String[]args){
  3. System.out.println("hello");
  4. }
@UserdefinedAnnotation(123)        public static void main(String[] args) {                System.out.println("hello");}
直接对其进行了省略。如果定义的属性名字不叫value,那么属性名字是不可以省略的哦!那是因为value属性名是annotation默认的一个属性名
2:数组类型
我们在自定义annotation中定义一个数组类型的属性,代码如下:
Java代码
  1. public@interfaceUserdefinedAnnotation{
  2. int[]value();
  3. }
public @interface UserdefinedAnnotation {        int[] value();}
我们如何使用呢,代码如下:
Java代码
  1. publicclassUseAnnotation{
  2. @UserdefinedAnnotation({123})
  3. publicstaticvoidmain(String[]args){
  4. System.out.println("hello");
  5. }
  6. }
public class UseAnnotation {                @UserdefinedAnnotation({123})        public static void main(String[] args) {                System.out.println("hello");        }}
注意1:其中123外面的大括号是可以被省略的,因为只有一个元素,如果里面有一个以上的元素的话,花括号是不能被省略的。比如{123,234}。
注意2:其中属性名value我们在使用的时候进行了省略,那是因为他叫value,如果是其他名字就不可以进行省略了必须是@UserdefinedAnnotation(属性名={123,234})这样的格式。
3:枚举类型
自从jdk5.0以后,java引进了枚举类型,我个人比较喜欢这样的方式尤其在进行业务逻辑判断的if或者switch子句中使用很方便,而且还不容易出错,大多时候都是作为一个函数的形式参数而存在,关于枚举类型的使用请查看相应的doc文档。
我们定义一个enum类型
Java代码
  1. packagecom.wangwenjun.annatation.userdefined;
  2. publicenumDateEnum{
  3. Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday
  4. }
  5. 然后在定义一个annotation
  6. packagecom.wangwenjun.annatation.userdefined;
  7. public@interfaceUserdefinedAnnotation{
  8. DateEnumweek();
  9. }
package com.wangwenjun.annatation.userdefined;public enum DateEnum {        Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday}然后在定义一个annotationpackage com.wangwenjun.annatation.userdefined;public @interface UserdefinedAnnotation {        DateEnum week();}
可以看出annotation中的属性类型为enum类型的,接下来我们看看他如何来使用
Java代码
  1. packagecom.wangwenjun.annatation.userdefined;
  2. publicclassUseAnnotation{
  3. @UserdefinedAnnotation(week=DateEnum.Sunday)
  4. publicstaticvoidmain(String[]args){
  5. System.out.println("hello");
  6. }
  7. }
package com.wangwenjun.annatation.userdefined;public class UseAnnotation {                @UserdefinedAnnotation(week=DateEnum.Sunday)        public static void main(String[] args) {                System.out.println("hello");        }}
在使用上也是很方便的,直接用来进行相关的引用,这样再应用的过程中就不会出现错误。
4:默认值
有时候我们在使用annotation的时候某一些属性值是会被经常使用到的,或者说他会有一个默认值给我们直接进行使用,那么我们在定义annotation的时候就可以为属性直接给出默认值,下面进行一下简单的示例。
Java代码
  1. public@interfaceUserdefinedAnnotation{
  2. Stringname()default"zhangsan";
  3. }
public @interface UserdefinedAnnotation {        String name() default "zhangsan";}
在使用的时候我们可以不进行指定
Java代码
  1. publicclassUseAnnotation{
  2. @UserdefinedAnnotation()
  3. publicstaticvoidmain(String[]args){
  4. System.out.println("hello");
  5. }
  6. }
public class UseAnnotation {                @UserdefinedAnnotation()        public static void main(String[] args) {                System.out.println("hello");        }}

当然我们也可以自己对其进行重新的设置,其中数组和枚举类型的默认值基本上类似,就不多做赘述了,自己进行测试即可。
5:注意
自定义Annotation spring annotation
● Annotation是不可以继承其他接口的,这一点是需要进行注意,这也是annotation的一个规定吧。
● Annotation也是存在包结构的,在使用的时候直接进行导入即可。
●Annotation类型的类型只支持原声数据类型,枚举类型和Class类型的一维数组,其他的类型或者用户自定义的类都是不可以作为annotation的类型,我查看过文档并且进行过测试。
三:Retention标记
Retention标记是告知编译器如何来处理我们自定义的annotation,指示注释类型的注释要保留多久。如果注释类型声明中不存在Retention 注释,则保留策略默认为 RetentionPolicy.CLASS。
查看他的源代码,会发现他有一个属性value,类型为RetentionPolicy,RetentionPolicy是一个枚举类型。其中有三个类型的值分别代表不同的意思。
CLASS 编译器将把注释记录在类文件中,但在运行时 VM 不需要保留注释。

RUNTIME 编译器将把注释记录在类文件中,在运行时 VM 将保留注释,因此可以反射性地读取。
SOURCE 编译器要丢弃的注释

下面是一段简短的定义代码示例。
Java代码
  1. packagecom.wangwenjun.annatation.userdefined;
  2. importjava.lang.annotation.Retention;
  3. importjava.lang.annotation.RetentionPolicy;
  4. @Retention(RetentionPolicy.RUNTIME)
  5. public@interfaceUserdefinedAnnotation{
  6. Stringname()default"zhangsan";
  7. }
package com.wangwenjun.annatation.userdefined;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;@Retention(RetentionPolicy.RUNTIME)public @interface UserdefinedAnnotation {        String name() default "zhangsan";}
从上面的实例中我们自定义的annotation是一个runntime范围的annotation,也就是说他会保持在源文件中并且也会在运行时由JVM自动调用。
我们先对它有一个感性的认识,知道有这么一个东西,在后面的文章中我会以一个示例对其进行详细的说明(会涉及到反射的相关东西)。其实Retention的名字翻译过来就是“保持力”的意思,说明的很清楚,就是我的annotation存放在哪些地方,也就是说我的annotation他的影响力到底在哪。
四:AnnotatedElement
在jdk5.0以后java反射包增加了这样一个接口,主要是用来对annotation进行操作的,其中AccessibleObject,Class, Constructor, Field, Method,Package都对其进行了实现继承。总共有以下四个方法:
<T extends Annotation>
T
getAnnotation(Class<T>annotationType)
如果存在该元素的指定类型的注释,则返回这些注释,否则返回 null。
Annotation[]
getAnnotations()
返回此元素上存在的所有注释。
Annotation[]
getDeclaredAnnotations()
返回直接存在于此元素上的所有注释。
boolean isAnnotationPresent(Class<? extendsAnnotation> annotationType)
如果指定类型的注释存在于此元素上,则返回 true,否则返回 false。
在接下来的章节中我们会进行说明。
五:Target 标记
在我们之前的实例中我们定义的annotation可以放在一个类的任何位置,那么我们是否可以对annotation的位置进行设置呢,答案是可以的,这就是我们所要说的的Target标记,他里面也有一个枚举类型的属性value,其中枚举类型为ElementType,有很多自定义的属性,如下所示:

ANNOTATION_TYPE
注释类型声明
CONSTRUCTOR
构造方法声明
FIELD
字段声明(包括枚举常量)
LOCAL_VARIABLE
局部变量声明
METHOD
方法声明
PACKAGE
包声明
PARAMETER
参数声明
TYPE
类、接口(包括注释类型)或枚举声明
上面的列表已经讲述的很清楚了,我们就不再进行说明了,直接来一个小程序进行演示吧,还是先来一个annotation,假设我们的annotation只能放在方法的前面
Java代码
  1. packagecom.wangwenjun.annatation.userdefined;
  2. importjava.lang.annotation.ElementType;
  3. importjava.lang.annotation.Target;
  4. @Target(ElementType.METHOD)
  5. public@interfaceUserdefinedAnnotation{
  6. Stringname()default"zhangsan";
  7. }
  8. packagecom.wangwenjun.annatation.userdefined;
  9. publicclassUseAnnotation{
  10. @UserdefinedAnnotation()
  11. publicstaticvoidmain(String[]args){
  12. System.out.println("hello");
  13. }
  14. }
package com.wangwenjun.annatation.userdefined;import java.lang.annotation.ElementType;import java.lang.annotation.Target;@Target(ElementType.METHOD)public @interface UserdefinedAnnotation {        String name() default "zhangsan";}package com.wangwenjun.annatation.userdefined;public class UseAnnotation {                @UserdefinedAnnotation()        public static void main(String[] args) {                System.out.println("hello");        }}
我们的annotation只能放在main方法上面放在其他的位置会出现错误。
六:Documented 标记
这个annotation非常简单,也非常容易理解,使用过javadoc命令的人都会很清楚,我们可以用javadoc命令将方法,类,变量等前面的注释转换成文档,在默认的情况下javadoc命令不会将我们的annotation生成再doc中去的,所以使用该标记就是告诉jdk让它也将annotation生成到doc中去,比如:
Java代码
  1. packagecom.wangwenjun.annatation.userdefined;
  2. importjava.lang.annotation.Documented;
  3. importjava.lang.annotation.ElementType;
  4. importjava.lang.annotation.Target;
  5. @Target(ElementType.METHOD)
  6. @Documented
  7. public@interfaceUserdefinedAnnotation{
  8. Stringname()default"zhangsan";
  9. }
package com.wangwenjun.annatation.userdefined;import java.lang.annotation.Documented;import java.lang.annotation.ElementType;import java.lang.annotation.Target;@Target(ElementType.METHOD)@Documentedpublic @interface UserdefinedAnnotation {        String name() default "zhangsan";}
七:Inherited标记
该标记的意思就是说,比如有一个类A,在他上面有一个标记annotation,那么A的子类B是否不用再次标记annotation就可以继承得到呢?答案是肯定的,我们做一个简单的演示,首先我们有一个annotation
Java代码
  1. packagecom.wangwenjun.annatation.userdefined;
  2. importjava.lang.annotation.Documented;
  3. importjava.lang.annotation.ElementType;
  4. importjava.lang.annotation.Inherited;
  5. importjava.lang.annotation.Retention;
  6. importjava.lang.annotation.RetentionPolicy;
  7. importjava.lang.annotation.Target;
  8. @Documented
  9. @Target(ElementType.TYPE)
  10. @Retention(RetentionPolicy.RUNTIME)
  11. @Inherited
  12. public@interfaceUserdefinedAnnotation{
  13. Stringname()default"zhangsan";
  14. }
package com.wangwenjun.annatation.userdefined;import java.lang.annotation.Documented;import java.lang.annotation.ElementType;import java.lang.annotation.Inherited;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Documented@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Inheritedpublic @interface UserdefinedAnnotation {        String name() default "zhangsan";}
接着定义一个父类
package com.wangwenjun.annatation.userdefined;

@UserdefinedAnnotation
public class ParentClass {

}
父类什么都没有干,只是一个空的类,并且有UserdefinedAnnotation的标记,然后我们写一个继承他的子类。
Java代码
  1. packagecom.wangwenjun.annatation.userdefined;
  2. publicclassChildClassextendsParentClass{
  3. }
package com.wangwenjun.annatation.userdefined;public class ChildClass extends ParentClass{        }
我们准备工作都已经做完了,现在就是利用反射机制进行一下简短的测试
Java代码
  1. packagecom.wangwenjun.annatation.userdefined;
  2. publicclassTestInherited{
  3. publicstaticvoidmain(String[]args){
  4. Class<ChildClass>clazz=ChildClass.class;
  5. booleanisExist=clazz.isAnnotationPresent(UserdefinedAnnotation.class);
  6. if(isExist){
  7. System.out.println("子类继承了父类的annotation");
  8. }else{
  9. System.out.println("子类没有继承父类的annotation");
  10. }
  11. }
  12. }
package com.wangwenjun.annatation.userdefined;public class TestInherited {        public static void main(String[] args) {                Class<ChildClass> clazz = ChildClass.class;                boolean isExist=clazz.isAnnotationPresent(UserdefinedAnnotation.class);                if(isExist){                        System.out.println("子类继承了父类的annotation");                }else{                        System.out.println("子类没有继承父类的annotation");                }        }}
打印结果为:子类继承了父类的annotation。可以看到子类果然继承了父类的annotation标记。

  

爱华网本文地址 » http://www.aihuau.com/a/25101015/247961.html

更多阅读

如何自定义文件夹图标 win7自定义文件夹图标

如何自定义文件夹图标——简介如何制作个性的文件夹图标,一眼就区别开不同的文件夹。如何自定义文件夹图标——工具/原料png图片转化ico图片软件美图秀秀如何自定义文件夹图标——方法/步骤如何自定义文件夹图标 1、从百度图片里

qq空间怎么免费设置背景 qq空间免费自定义背景

qq空间怎么免费设置背景——简介QQ空间采用模块化的设计理念,为我们自定义QQ版面提供了方便的方法,只需要通常简单的拖动即可设计出唯美的个性化风格空间。下面就与小编一起来学习一下QQ空间背景的设计方法。qq空间怎么免费设置背景

怎样自定义QQ空间开场动画? qq空间开场动画diy

相信大家都想把自己的QQ空间装扮的漂漂亮亮的,那么自定义一个开场动画是分不开的,本文就教大家怎样自定义QQ空间开场动画。首先提醒大家的是:自定义QQ空间开场动画必须是黄钻三级以上。具体制作步骤如下:1、 打开QQ空间2、 点击装扮,

如何设置毕业论文的自定义格式样式及应用格式 毕业论文样式

如何设置毕业论文的自定义格式样式及应用格式——简介毕业论文是对大学学习的一份总结,都希望为自己的大学生活画上完美的句号,提交一份优秀的毕业论文。一份优秀的毕业论文是以规范的格式为前提的,所以在编写论文时,需要先按照学校的规

修改开机画面自定义开机画面 开机画面修改

修改开机画面(自定义开机画面)——简介自定义开机画面。让自己的电脑登录界面看起来更符合自己的要求。修改开机画面(自定义开机画面)——工具/原料logonui.exe修改开机画面(自定义开机画面)——方法 1 软件修改修改开机画面(自定义开机画

声明:《自定义Annotation spring annotation》为网友浅蓝铯啲嗳分享!如侵犯到您的合法权益请联系我们删除