zoukankan      html  css  js  c++  java
  • Annotation

    在spring、hibernate等流行的开源框架中,基本上来进行配置的方式有两种,一种是基于配置文件的配置,注入applicationContext.xml或者是hbm.xml,同样另一种方式则是基于注解的配置,可以说使用注解的配置相当的简洁明了,所以这里就再来回顾一下什么是Annotation。

    一、Annotation基本概念

    Annotation是jdk5以后出现的新特性,在jdk中,其内置了许多自己的Annotation,例如@Override,@SuppresWarning,@Deprecated等等,其中一些Annotation是标志性的Annotation,例如@Override就是表示这个类要重写父类的方法。

    我们首先要清楚的知道一点,其实Annotation和Class、Interface这些一样,都是类级别的,而且我们创建的每一个Annotation都默认的继承了java.lang.annotation.Annotation这个接口,注意:如果一个接口继承了这个Annotation接口,那么这个接口并不是一个Annotation

    我们接下来自己创建一个简单的Annotation:

    public @interface MyAnnotation
    {
        String value();
        String name() default "xiaoluo";
    }

    这样就定义了我们自己的一个Annotation了,它的标识符就是  @interface,同样,Annotation里面可以定义我们的属性,例如,上面的例子我就定义了两个String类型的属性,一个是value属性,一个是name属性,注意:在Annotation里定义属性,属性后面都要加上括号。同时我们还可以给Annotation的属性设置默认值,通过 default 这个关键字来设置默认值,接下来我们就可以使用我们自己定义的Annotation了:

    @MyAnnotation(value="hello", name="world")
    public class AnnotationTest
    {
        @MyAnnotation("xiaoluo")
        public void hello()
        {
            System.out.println("This is my Annotation!");
        }
    }

    我们看到,这个时候我们就可以在类上面、方法上面使用我们的Annotation了,注意:在自己定义的Annotation中,如果为其设置了属性,则我们必须要给其属性赋值

    在上面的例子中,我们看到 @MyAnnotation(value="hello", name="world") 这里就是给其 value属性和name 属性赋值,而在下面的那个Annotation中:

    @MyAnnotation("xiaoluo"),我们没有指定其属性名,那么它是赋值给谁呢?在Annotation中,如果我们定义了一个 value 属性,那么我们在使用该Annotation,给其赋值时,可以不用写出属性的名字,即value

    怎么样,简单吧,这样我们就定义并使用了我们的Annotation了。

    二、Retention和RetentionPolicy

    在初步了解了Annotation之后,我们再来看看Retention和RetentionPolicy这两个概念,Retention的中文意思是,保留、持有,同样,Retention也是一个Annotation,通过这个注解,我们可以指定我们自己定义的Annotation的保留范围,其默认值是有三个,是枚举类型的值,RetentionPolicy.CLASS(这个是Retention的默认值,表示这个Annotation会被编译到class文件当中), RetentionPolicy.RESOURCE(这个表示Annotation仅仅在编译的时候有效,起到提示作用,并不会被编译到class文件当中去), RetentionPolicy.RUNTIME(这个表示Annotation不仅会被编译到class文件当中,而且会在JVM运行中也可以得到这个Annotation,这样我们就可以通过反射来得到Annotaion,并对其进行一些操作了),我们来看看jdk自带的一些Annotation,其Retention分别是什么:

    @Retention(value=SOURCE)
    public @interface Override
    
    @Retention(value=SOURCE)
    public @interface SuppressWarnings
    
    @Retention(value=RUNTIME)
    public @interface Deprecated

    我们看到,Deprecated的RetentionPolicy是RUNTIME的,这样我们可以通过反射在运行时得到其Annotation,接下来我们自己来指定我们刚定义的MyAnnotation为RUNTIME:

    @Retention(RetentionPolicy.RUNTIME)
    public @interface MyAnnotation
    {
        String value();
        String name() default "xiaoluo";
    }

    这个时候,我们定义的Annotation就会被编译到class文件当中去,并且在运行时可以得到它,接下来我们来通过一个例子来看看如何使用反射机制得到我们的Annotation以及我们设置的属性值,java的API指定了访问得到Annotation的方法,我们的Class,Method,Constructor等等这些都默认实现了 AnnotatedElement 这个接口,这个接口定义了四个常用的方法:

    <T extends Annotation> T  getAnnotation(Class<T> annotationClass)    // 根据Annotation.class得到这个Annotation
    
    Annotation[] getAnnotations()    //  得到一个Annotation数组
    
    Annotation[] getDeclaredAnnotations()  //  也是得到一个Annotation数组
    
    boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)    //  判断是否为被当前的Annotation所标识
    @MyAnnotation("hello")
    public class AnnotationTest
    {
        @MyAnnotation(value="xiaoluo", name="welcome")
        public void hello()
        {
            System.out.println("This is my Annotation!");
        }
        
        public static void main(String[] args) throws Exception
        {
            //    得到AnnotationTest这个类的 class 对象
            Class<AnnotationTest> clazz = AnnotationTest.class;
            
            //    得到AnnotationTest的一个实例对象
            AnnotationTest test = (AnnotationTest)clazz.newInstance();
            
            //    得到方法名为hello的Method对象
            Method method = clazz.getMethod("hello", new Class[]{});
        
            //    判断hello这个方法是否被MyAnnotation这个注解所标记
            if(method.isAnnotationPresent(MyAnnotation.class))
            {
                //    得到我们的MyAnnotation这个注解
                MyAnnotation myAnnotation = (MyAnnotation)method.getAnnotation(MyAnnotation.class);
                
                System.out.println(myAnnotation.name() + ", " + myAnnotation.value());
                
                method.invoke(test, new Object[]{});
            }
        }
    }

    我们来看看,因为我们的@MyAnnotation设置了其RetentionPolicy为RUNTIME,所以我们可以在通过反射在运行时得到该Annotation对象,结果输出为:

    welcome, xiaoluo
    This is my Annotation!

    通过这个例子,我想大家应该知道了RecentPolicy的三个值的含义了吧,我们都可以设置其为RUNTIME,这样就可以在运行时对其进行判断来处理我们的业务逻辑了

    三、Target和ElementType

    最后我们来看看Target和ElementType这两个东东,Target这个也是一个注解,这个Annotation是用来指定我们的Annotation可以标志的范围,例如定义在类上,定义在方法上等等,其value就是通过ElementType来指定的,我们来看看ElementType有哪些值:

    ANNOTATION_TYPE     // 可以定义在Annotation上
    
    CONSTRUCTOR         // 可以定义在构造函数上
    
    FIELD          // 可以定义属性上
    
    LOCAL_VARIABLE    // 可以定义在方法的局部变量上
    
    METHOD         // 可以定义在方法上
    
    PACKAGE        // 可以定义在包上
      
    PARAMETER       // 可以定义在方法的参数上
    
    TYPE         // 可以定义在类上、接口上

    我们也可以在刚才定义的MyAnnotation上设置我们的Target:

    @Target({ElementType.TYPE, ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface MyAnnotation
    {
        String value();
        String name() default "xiaoluo";
    }

    表示MyAnnotation可以定义在类上还有方法上,如果在其他地方定义该注解,则会编译不通过

    好了,Annotation的知识基本就是这些了,主要讲解了Annotation的基本概念以及其的一些特性

  • 相关阅读:
    [Swift]LeetCode300. 最长上升子序列 | Longest Increasing Subsequence
    备忘录模式之C++实现
    leecode 题解 || Merge k Sorted Lists 问题
    数学三大危机
    singlefile.py
    Data Url生成工具之HTML5 FileReader实现
    算法题:打印1到最大的n位数
    java.lang.NoClassDefFoundError: org/apache/commons/lang/xwork/StringUtils
    hdu 1181 变形课
    postgis经常使用函数介绍(一)
  • 原文地址:https://www.cnblogs.com/xiaoluo501395377/p/3381249.html
Copyright © 2011-2022 走看看