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

    Annotation(注解)是JDK5.0版本开始引入的,是附加在代码中的一些元信息,用于一些工具在编译、运行时进行解析和使用,起到说明、配置的功能。注解不会直接影响到程序的语义,只是作为注解(标识)存在,可以通过反射机制编程实现对这些元数据的访问。

    在Java开发过程中,我们过去比较常见的方式是将软件的各种配置参数存贮在XML文件中,程序运行时从XML配置文件中读取出各配置参数进行运行时环境配置。这个方式使用程序运行灵活的同时也带来一个问题:就是XML配置文件越来越多,不易管理。注解引进后,减少配置、使用注解替代部分XML配置慢慢变成一种趋势。从某种角度来讲,注解具有XML配置的功能,它可有不同的预定义属性,属性值可以在声明该标时指定。在代码中使用注解,就相当于把一部分元数据从XML文件移到了代码本身,并在代码中进行管理和维护。这使得配置文件变得越来越少,而规范约定和注解代替了一些繁琐的配置信息。我们可以在许多Java开源项目中看到这种“零配置”的思维。

    那么如何来自定义和使用注解呢(这里主要说明运行时使用注解)? 

    要实现一个自定义注解,首先需要通过关键字@interface来定义一个注解标记。例:

    @Retention(RetentionPolicy.RUNTIME)

    @Target(ElementType.METHOD)

    public @interface MyAnnotation {

        String name() default "abc";

        MyEnum type() default MyEnum.A;

        enum MyEnum {

            A, B

        }

    }

    在上例中,通过元注解来描述该注解的使用范围( @Target )、生命周期( @Retention ),并定义了一个注解标记。我们对@Target、@Retention进行一个简单说明:

    @Target 用于描述注解的使用范围(即:被描述的注解可以用在什么地方),其取值有:

    取值

    描述

    CONSTRUCTOR

    构造器声明

    FIELD

    域声明

    LOCAL_VARIABLE

    局部变量声明

    METHOD

    方法声明

    PACKAGE

    包声明

    PARAMETER

    参数声明

    TYPE

    类或接口声明

    @Retention 用于描述注解的生命周期(即:被描述的注解在什么范围内有效),其取值有:

    取值

    描述

    SOURCE

    注解将被编译器丢弃

    CLASS

    注解在class文件中可用,但会被VM丢弃

    RUNTIME

    将在运行期保留注解,可通过反射机制读取注解的信息

    定义好注解标记后,我们就可以在代码中使用这个注解了,如:

    @ MyAnnotation (type="B”, name="Hello World")

    public void anyMethod() {

             ... ...

    }

    但要使用注解标记工作起来,我们还需要编写这个注解标记的处理器(注解处理器是一段用于解释或处理自定义注解标记的代码),它是通过java的反射机制来进行解析。如下:

    public class MyAnnotationTest {

        @MyAnnotation(name = "a", type = MyAnnotation.MyEnum.B)

        public void execute() {

            System.out.println("method");

        }

        public static void main(String[] args) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {

            MyAnnotationTest annotationTest = new MyAnnotationTest();

            //获取MyAnnotationTest的Class实例

            Class<MyAnnotationTest> c = MyAnnotationTest.class;

            //获取需要处理的方法Method实例

            Method method = c.getMethod("execute", new Class[]{});

            //判断该方法是否包含MyAnnotation注解

            if (method.isAnnotationPresent(MyAnnotation.class)) {

                //获取该方法的MyAnnotation注解实例

                MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class);

                //执行该方法

                method.invoke(annotationTest, new Object[]{});

                //获取myAnnotation

                String value = myAnnotation.name();

                System.out.println(value);

            }

            //获取方法上的所有注解

            Annotation[] annotations = method.getAnnotations();

            for (Annotation annotation : annotations) {

                System.out.println(annotation);

            }

        }

    }

     以上代码仅仅是示意如何使用反射来得到注解信息。

    在实际的应用中,我们可以采用注解来描述数据,大致过程如此:创建一个JavaBean,使用注解来描述这个JavaBean的语义。这个用法类似于用XML来描述一个数据,每个字段注解对应于XML的属性元素,字段的取值对应于XML的属性值,当然数据本身也可用XML来进行描述。这种方式常见于接口间的数据描述,最常见的如数据库连接信息。

    另一种用法,就是类似于使用XML来配置运行时所需要的数据,比如我们常见的Spring MVC的注解配置方式,如:

           @RequestMapping(value = {"xxx"}, method = {org.springframework.web.bind.annotation.RequestMethod.POST})

    表示POST请求输入为xxx时,调用该方法。如果我们在XML中进行配置,就类似于:

           <value>xxx</value><method>POST</method><invoke>xxx.xxx(xxx类的xxx方法)</invoke>

    这种方式在过去的开发中,我们是常见的。比如网管软件开发时,对多网元多版本进行控制时,我们过去就常将网元类型、版本和它的处理方法配置在一个配置文件中,而这种方式也可用注解方式来解决。

    另外,就是在某些API方法中使用注解对API的调用条件进行限制等。

    当然这些处理都需要一个注解标记处理框架。需要注意的是,Annoation的表达能力有限,不如XML的强,所以在应用时应该考虑使用那种方式更简便。

    附:

    java5.0在java.lang包中定义了3种标准的annotation类型:A. Override,B. Deprecated,C. SuppressWarnings。并且还定义了4个标准的meta-annotation类型,它们被用来提供对其它annotation类型作说明:@Target、@Retention、@Documented、@Inherited。

  • 相关阅读:
    Atcoder D
    51nod 1201 整数划分(dp)
    Atcoder D
    Atcoder C
    codeforces 812 E. Sagheer and Apple Tree(树+尼姆博弈)
    codeforces 811 D. Vladik and Favorite Game(bfs水题)
    codeforces 811 E. Vladik and Entertaining Flags(线段树+并查集)
    codeforces 811 C. Vladik and Memorable Trip(dp)
    1449 砝码称重(思维)
    SQL大量数据查询的优化 及 非用like不可时的处理方案
  • 原文地址:https://www.cnblogs.com/jevo/p/2992441.html
Copyright © 2011-2022 走看看