美文网首页程序员Java学习笔记
java的Anotation机制,以及在WF中的应用

java的Anotation机制,以及在WF中的应用

作者: 一只小哈 | 来源:发表于2016-05-29 15:34 被阅读289次

    在写代码的时候,总会在类名或者方法名的上面出现@xxx这样的语法,开始的时候我是不会用这种注解符号的,只明白一些注解是起说明作用的如@Overwrite这种,后来接触了Spring之后才明白,这种注解其实有比较大的用处,结合一些博文和自己的实际应用,记录下自己使用的注解和框架中应用注解的实现机制。
    1.java中注解的基本使用方式和声明
    (1)元注解
    1.@Target,
    2.@Retention,
    3.@Documented,
    4.@Inherited
    以上几个元注解是为真正我们要实现的注解服务的。
    1.@Target 此字段是用于描述注解可以被应用的范围,可被使用的范围有 packages、types(类、接口、枚举、Annotation类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch参数)
    可以取的值有:
    1.CONSTRUCTOR:用于描述构造器
    2.FIELD:用于描述域
    3.LOCAL_VARIABLE:用于描述局部变量
    4.METHOD:用于描述方法
    5.PACKAGE:用于描述包
    6.PARAMETER:用于描述参数
    7.TYPE:用于描述类、接口(包括注解类型) 或enum声明
    Target可以被添加到目标注解的头部,表示目标注解的应用范围。
    2.@Retention定义了该Annotation被保留的时间长短:简单来说就是目标注解的作用范围;
    可以取的值为:
    1.SOURCE:在源文件中有效(即源文件保留)
    2.CLASS:在class文件中有效(即class保留)
    3.RUNTIME:在运行时有效(即运行时保留)
    一般都是用于RUNTIME
    3.@Documented用于描述其它类型的annotation应该被作为被标注的程序成员的公共API
    用于声明当前修饰的注解能不能生成在java doc中,此参数是没有成员的。
    4.@Inherited 元注解是一个标记注解,@Inherited阐述了某个被标注的类型是被继承的。如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类。
    此元注解我用到的不多,就不多说了
    (2).自定义注解的实现
    自定义注解其实是基于元注解去实现的一种注解,通常主要用于拦截器或者成员的声明等,使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口,由编译程序自动完成其他细节。在定义注解时,不能继承其他的注解或接口。@interface用来声明一个注解,其中的每一个方法实际上是声明了一个配置参数。方法的名称就是参数的名称,返回值类型就是参数的类型(返回值类型只能是基本类型、Class、String、enum)。可以通过default来声明参数的默认值。
    下面自定义实现一个java的Annotation:
    首先定义一个Annotation:

    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    @Target(ElementType.FIELD)//声明的注解要加到字段是上
    @Retention(RetentionPolicy.RUNTIME)//声明为运行时要使用的
    public @interface ColorAnnotation {
    public String value() default "red";//默认值
    }
    

    定义一个使用此注解的类:

    public class ColorTest {
        @ColorAnnotation("yellow")
        public String color;
    }
    

    只定义和使用注解是远远达不到目的的,接下来我们还需要对注解进行解析

    Java使用Annotation接口来代表程序元素前面的注解,该接口是所有Annotation类型的父接口。除此之外,Java在java.lang.reflect 包下新增了AnnotatedElement接口,该接口代表程序中可以接受注解的程序元素,该接口主要有如下几个实现类:

    Class:类定义
      Constructor:构造器定义
      Field:累的成员变量定义
      Method:类的方法定义
      Package:类的包定义

    java.lang.reflect 包下主要包含一些实现反射功能的工具类,实际上,java.lang.reflect 包所有提供的反射API扩充了读取运行时Annotation信息的能力。当一个Annotation类型被定义为运行时的Annotation后,该注解才能是运行时可见,当class文件被装载时被保存在class文件中的Annotation才会被虚拟机读取。
      AnnotatedElement 接口是所有程序元素(Class、Method和Constructor)的父接口,所以程序通过反射获取了某个类的AnnotatedElement对象之后,程序就可以调用该对象的如下四个个方法来访问Annotation信息:

    方法1:<T extends Annotation> T getAnnotation(Class<T> annotationClass): 返回改程序元素上存在的、指定类型的注解,如果该类型注解不存在,则返回null。
      方法2:Annotation[] getAnnotations():返回该程序元素上存在的所有注解。
      方法3:boolean is AnnotationPresent(Class<?extends Annotation> annotationClass):判断该程序元素上是否包含指定类型的注解,存在则返回true,否则返回false.
      方法4:Annotation[] getDeclaredAnnotations():返回直接存在于此元素上的所有注释。与此接口中的其他方法不同,该方法将忽略继承的注释。(如果没有注释直接存在于此元素上,则返回长度为零的一个数组。)该方法的调用者可以随意修改返回的数组;这不会对其他调用者返回的数组产生任何影响。
    接下来是对注解进行解析:

    import java.lang.reflect.Field;
    
    public class ColorPaser {
        public static void parse(Class<?> clazz){
            Field fields[] = clazz.getDeclaredFields();
            for(Field f : fields){
                if(f.isAnnotationPresent(ColorAnnotation.class)){
                    ColorAnnotation color = f.getAnnotation(ColorAnnotation.class);
                    String colorStr = color.value();
                    System.out.println(colorStr);
                }
            }
        }
        public static void main(String args[]){
            ColorPaser.parse(ColorTest.class);
        }
    }
    

    这样就实现了对注解的解析处理。当然实际应用中这种注解的解析模式可以应用到拦截器上面,我们现在用的框架就是自己定义实现了一个通过注解进行的拦截器。然后在Filter中进行解析请求 映射Controller解析到对应的注解进行对请求的拦截。

    相关文章

      网友评论

        本文标题:java的Anotation机制,以及在WF中的应用

        本文链接:https://www.haomeiwen.com/subject/hgdqdttx.html