zoukankan      html  css  js  c++  java
  • Java Annotation自定义注解详解

    在开发过程中总能用到注解,但是从来没有自己定义过注解。最近赋闲在家,研究整理了一番,力求知其然知其所以然。

    本文会尝试描述什么是注解,以及通过一个Demo来说明如何在程序中自定义注解。Demo没有实际意义,仅仅只是为了注解而使用注解。

     

    1、什么是注解?

           注解是在jdk 1.5开始提供的功能,目前被广泛使用。以下是引用《Java疯狂讲义》第十四章关于注解的描述:

           “Annotation其实是代码里的特殊标记,这些标记可以在编译、类加载、运行时被读取,并执行响应的处理。通过使用Annotation,程序开发人员可以在不改变原有逻辑的情况下,在源文件嵌入一些补充信息。代码分析工具、开发工具和部署工具可以通过这些补充信息进行验证或者进行部署。”

          

           JUnit单元测试就是基于注解的。我认为使用动态代理和注解,自己完全也可以写一个MyJUnit。

          

    2、Demo的实现:

    注解文件:

    这个文件主要包含了三个部分:

           A.注解文件使用@interface来声明。

           B.在A外层有元注解声明(注解的注解),主要的作用就是对我们自定义注解的执行范围、时期进声明。下面是注解的注解含义说明:

    @Documented:指示某一类型的注释将通过 javadoc 和类似的默认工具进行文档化。应使用此类型来注释这些类型的声明:其注释会影响由其客户端注释的元素的使用。如果类型声明是用 Documented 来注释的,则其注释将成为注释元素的公共 API 的一部分。

    @Target:指示注释类型所适用的程序元素的种类。如果注释类型声明中不存在 Target 元注释,则声明的类型可以用在任一程序元素上。如果存在这样的元注释,则编译器强制实施指定的使用限制。例如,此元注释指示该声明类型是其自身,即元注释类型。它只能用在注释类型声明上。

    @Inherited:指示注释类型被自动继承。如果在注释类型声明中存在 Inherited 元注释,并且用户在某一类声明中查询该注释类型,同时该类声明中没有此类型的注释,则将在该类的超类中自动查询该注释类型。此过程会重复进行,直到找到此类型的注释或到达了该类层次结构的顶层 (Object) 为止。如果没有超类具有该类型的注释,则查询将指示当前类没有这样的注释。注意,如果使用注释类型注释类以外的任何事物,此元注释类型都是无效的。还要注意,此元注释仅促成从超类继承注释;对已实现接口的注释无效。

    @Retention:指示注释类型的注释要保留多久。如果注释类型声明中不存在 Retention 注释,则保留策略默认为 RetentionPolicy.CLASS。

    C.方法名就是参数名,返回值类型就是参数的类型,通过default来设置方法的默认值。

     

    下面是代码:

     1 package com.array7.annotationTest;
     2 
     3 import java.lang.annotation.Documented;
     4 import java.lang.annotation.ElementType;
     5 import java.lang.annotation.Inherited;
     6 import java.lang.annotation.Retention;
     7 import java.lang.annotation.RetentionPolicy;
     8 import java.lang.annotation.Target;
     9 
    10 @Documented
    11 @Target(ElementType.METHOD)
    12 @Inherited
    13 @Retention(RetentionPolicy.RUNTIME)
    14 public @interface MethodInfo {
    15     String author() default "array7";    // 作者
    16     String date();    // 日期
    17     double version() default 1.0;    // 版本号
    18     String comments();    // 注释
    19 }

    然后定义个调用注解的类:

     1 package com.array7.annotationTest;
     2 
     3 public class AnnotationExample {
     4     /**
     5      * 非静态方法
     6      * @param msg
     7      */
     8     @MethodInfo(author = "七郎", comments = "方法测试注释:print10", date = "2013-11-29", version = 1.0)
     9     public void print10(Object msg) {
    10         System.out.println(msg);
    11     }
    12     
    13     /**
    14      * 静态方法
    15      */
    16     @MethodInfo(author = "七郎", comments = "方法测试注释:print20", date = "2013-11-20", version = 2.0)
    17     public static void print20() {
    18         System.out.println("test");
    19     }
    20 }

    最后就是注解解析类(简单起见我将代码写在了main方法里):

     1 package com.array7.annotationTest;
     2 
     3 import java.lang.annotation.Annotation;
     4 import java.lang.reflect.InvocationTargetException;
     5 import java.lang.reflect.Method;
     6 
     7 public class AnnotationParsing {
     8     public static void main(String[] args) {
     9         try {
    10             Class<?> clazz = Class.forName("com.array7.annotationTest.AnnotationExample");    // 这里可以封装成动态代理类。
    11             // Class clazz = AnnotationParsing.class.getClassLoader().loadClass("com.array7.annotationTest.AnnotationExample");    // 这种方式也OK。
    12             for (Method method : clazz.getMethods()) {
    13                 if (method.isAnnotationPresent(MethodInfo.class)) {
    14                     for (Annotation anno : method.getAnnotations()) {
    15                         System.out.println("Annotation in Method [" + method + "]:" + anno);
    16                         MethodInfo methodInfo = method.getAnnotation(MethodInfo.class);
    17                         if (methodInfo.version() == 1.0) {
    18                             method.invoke(clazz.newInstance(), methodInfo.comments());
    19                         } else if (methodInfo.version() == 2.0) {
    20                             method.invoke(null);
    21                         }
    22                     }
    23                 }
    24             }
    25         } catch (SecurityException e) {
    26             e.printStackTrace();
    27         } catch (ClassNotFoundException e) {
    28             e.printStackTrace();
    29         } catch (IllegalAccessException e) {
    30             e.printStackTrace();
    31         } catch (IllegalArgumentException e) {
    32             e.printStackTrace();
    33         } catch (InvocationTargetException e) {
    34             e.printStackTrace();
    35         } catch (InstantiationException e) {
    36             // TODO Auto-generated catch block
    37             e.printStackTrace();
    38         }
    39         
    40     }
    41 }

    程序最后输出:

    Annotation in Method [public void com.array7.annotationTest.AnnotationExample.print10(java.lang.Object)]:@com.array7.annotationTest.MethodInfo(author=七郎, version=1.0, comments=方法测试注释, date=2013-11-20)
    方法测试注释
    Annotation in Method [public static void com.array7.annotationTest.AnnotationExample.print20()]:@com.array7.annotationTest.MethodInfo(author=七郎, version=2.0, comments=方法测试注释, date=2013-11-20)
    test

    一个从CSDN出逃的人~~

    http://blog.csdn.net/array7

  • 相关阅读:
    微服务架构技术栈选型手册(万字长文)
    Visual Studio 2013 always switches source control plugin to Git and disconnect TFS
    Visual Studio 2013 always switches source control plugin to Git and disconnect TFS
    MFC对话框中使用CHtmlEditCtrl
    ATL开发 ActiveX控件的 inf文件模板
    ActiveX: 如何用.inf和.ocx文件生成cab文件
    Xslt 1.0中使用Array
    如何分隔两个base64字符串?
    An attempt was made to load a program with an incorrect format
    JQuery 公网 CDN
  • 原文地址:https://www.cnblogs.com/liushijie/p/4711647.html
Copyright © 2011-2022 走看看