`
xyheqhd888
  • 浏览: 403693 次
  • 性别: Icon_minigender_1
  • 来自: 秦皇岛
社区版块
存档分类
最新评论

meta-annotation

阅读更多

 1. 所谓meta-annotation就是Annotation类型的数据,也就是Annotation类型的Annotation,在定义Annotation类型时,为Annotation类型加上Annotation可以为处理Annotation类型的分析工具提供更多的信息。

2. java.lang.annotation.Retention类型可以在您定义Annotation类型时,指示编译器该如何对待自定义的Annotation类型,编译器默认会将Annotation信息留在.class文件中,但不被JVM读取,而仅用于编译器或工具程序运行时提供信息。

3. 在使用Retention类型时,需要提供java.lang.annotation.RetentionPolicy的枚举类型。RetentionPolicy的枚举类型定义如下所示:

package java.lang.annotation;
public enum RetentionPolicy
{
    SOURCE, //编译器处理完Annotation信息后就没事了
   CLASS,   //编译器将Annotation存储于class文件中,默认
   RUNTIME,  //编译器将Annotation存储于class文件中,可由VM读入
}

      RetentionPolicy为SOURCE的例子是@SuppressWarning,这个信息的作用仅在编译时期告知编译器来抑制,所以不必将这个信息存储于.class文件中。

      RetentionPolicy为RUNTIME的时机,可以像是您使用Java设计一个程序代码分析工具,您必须让VM能读出Annotation信息,以便在分析程序时使用,搭配反射机制,就可以达到这个目的。

      J2SE 5.0新增了java.lang.reflect.AnnotatedElement接口,其中定义有4个方法:

public Annotation getAnnotation(Class annotationType);
public Annotation[] getAnnotations();
public Annotation[] getDeclaredAnnotations();
public boolean isAnnotationPresent(Class annotationType);

      Class,Field,Method,Package,Constructor等类,都实现了AnnotatedElement接口,所以可以从这些类实例上,分别取得标示于其上的Annotation与相关信息。由于是在执行时期读取Annotation信息,所以定义Annotation时必须设定RententionPolicy为RUNTIME,也就是可以在VM中读取Annotation信息。举例来说,假设设计了一个如下的Annotation。

package ysu.hxy;

import java.lang.annotation.Retention;
import java.lang.annotaion.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface someAnnotation
{
    String value();
    String name();
}

 由于RetentionPolicy为RUNTIME,编译器在处理SomeAnnotation时,会将Annotation及给定的相关信息编译至.class文件中,并设定为VM可以读出Annotation信息。接着可以使用如下范例来使用我们刚才定义的SomeAnnotaion。    

package ysu.hxy;

public class SomeClass3
{
	@SomeAnnotation(
		value = "annotation value1",
		name = "annotation name1"
    )
	
	public void doSomething()
	{
		//...
	}
}

 现在假设要设计一个源代码分析工具来分析所设计的类,一些分析时所需的信息已经使用Annotation标示于类中了,可以在执行时读取这些Annotation的相关信息。下面是个简单的范例:

package ysu.hxy;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

public class AnalysisApp
{
	public static void main(String[] args) throws NoSuchMethodException 
	{
		Class<SomeClass3> c= SomeClass3.class;

		// 因为SomeAnnotation标示于doSomething()方法上
		//所以要取得doSomething()方法的Method实例 
		Method method = c.getMethod("doSomething");

		//如果SomeAnnotation存在
		if(method.isAnnotationPresent(SomeAnnotation.class))
		{
			System.out.println("找到@Annotation");
			//取得Annotation
			SomeAnnotation annotation = 
				 method.getAnnotation(SomeAnnotation.class);
			//取得value成员值
			System.out.println("\tvalue = " + annotation.value());
			//取得name成员值
			System.out.println("\tname = " + annotation.name());
		}
		else
		{
			System.out.println("没有找到@SomeAnnotation");
		}

		//取得doSomething()方法上所有的Annotation 
		Annotation[] annotations = method.getAnnotations();
        //显示Annotation名称 
		for(Annotation annotation : annotations)
		{
			System.out.println("Annotation名称:"+ annotation.annotationType().getName());
		}
	}
}

 

 若Annotation标示于方法上,就要取得方法的Method代表实例。同样地如果Annotation标示于类或包上,就要分别取得类的Class代表实例或者包的Package代表实例。之后可以使用实例上的getAnnotation()等相关方法,以测试是否可取得Annotation或进行其他操作。此示例的执行结果如下:

D:\hxy>java ysu.hxy.AnalysisApp
找到@Annotation
        value = annotation value1
        name = annotation name1
Annotation名称:ysu.hxy.SomeAnnotation

4. 限定Annotation使用对象@Target

    在定义Annotation类型时,使用java.lang.annotation.Target可以定义其适用的时机。在定义时要指定java.lang.annotation.ElementType的枚举值之一:

package ysu.hxy;

public enum ElementType
{
    TYPE,  //适用class,interface,enum
    FIELD, //适用field
    METHOD,//适用method
    PARAMETER,  //适用method之上的parameter
    CONSTRUCTOR, //适用constructor
    LOCAL_VARIABLE, // 适用区域变量
   ANNOTATION_TYPE, //适用annotation类型
   PACKAGE  //适用package
}

 举例说明,假设定义Annotation类型时,要限定它只能适用于构造函数与方法成员,则可以用以下代码来定义:

package ysu.hxy;

import java.lang.annotation.Target;
import java.lang.annotation.ElementType;

@Target({ElementType.CONSTRUCTOR,ElementType.METHOD})
public @interface MethodAnnotation{}

 如果尝试将MethodAnnotation标示于类之上,例如:

@ysu.hxy.MethodAnnotation
public class SomeoneClass
{
	public void doSomething()
	{
		//....
	}
}

 编译时会发生以下错误:

D:\hxy>javac -d . SomeoneClass.java
SomeoneClass.java:1: 注释类型不适用于该类型的声明
@ysu.hxy.MethodAnnotation
^
1 错误
5. 要求为API文件的一部分@Documented

   在制作Java Doc文件时,并不会默认将Annotation的数据加入到文件中,例如设计了以下的OneAnnotaion类型:

 

package ysu.hxy;
public @interface OneAnnotation{}

 并次之用在以下的程序中:

 

public class SomeoneClass
{
   @ysu.hxy.OneAnnotation
   public void doSomething()
   {
      //...
   }
}

 

试着使用javadoc程序来产生Java Doc文件,会以现文件中并不会有Annotation的相关信息。Annotation用于标示程序代码以便分析工具使用相关信息,有时Annotation包括了重要的信息,您也许会想要在使用者制作Java Doc文件的同时,也一并将Annotation的信息加入至API文件中,所以在定义Annotation类型时,可以使用java.lang.annotation.Documented。如下范例:

package ysu.hxy;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface TwoAnnotation{}

  使用java.lang.annotation.Documented为定义的Annotation类型加上Annotation时,必须同时使用Retention来指定编译器将信息加入.class文件,并可以由VM读取,也就是要设定RententionPolicy为RUNTIME。接着可以使用这个Annotation,并产生Java Doc文件,这时可以看到文件中包括了@TwoAnnotation信息。

6. 子类是否继承父类的annotation@Inherited

    在定义Annotation类型并使用于程序代码上后,默认父类中的Annotation并不会被继承至子类中。可以在定义Annotation类型时加上java.lang.Annotation.Inherited类型的Annotation,这让您定义的Annotation类型在被继承后仍可以保留在子类中。

package ysu.hxy;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotaion.Inherited;

@Retention(RetentionPolicy.RUNTIME}
@Inherited
public @interface ThreeAnnotation
{
   String value();
   String name();
}

 可以在下面的程序中使用@ThreeAnnotaion:

public class SomeoneClass
{
    @ysu.hxy.ThreeAnnotation
    (
         value = "unit",
         name = "debug1"
    )
    
    public void doSomething()
    {
        //....
    }
}

 如果有一个类继承了SomeoneClass类,则理想上@ThreeAnnotation也会被继承下来。不过事实上@Inherited在Sun JDK 5.0里还没有作用。 

分享到:
评论

相关推荐

    Java中三种标准注解和四种元注解.pdf

    Java5.0定义了4个标准的meta-annotation类型,它们被⽤来提供对其它 annotation类型作说 明。Java5.0定义的元注解:  1.@Target,  2.@Retention,  3.@Documented,  4.@Inherited  这些类型和它们所⽀持的类在...

    java元注解.docx

    在Java中,元注解(Meta-Annotation)是一种特殊类型的注解,用于注解其他注解。元注解提供对注解的元数据进行定义和控制的能力。Java中提供了几个预定义的元注解,用于定制和修改注解的行为。让我们详细介绍一下...

    JavaSE-注解与反射(框架底层实现机制)

    元注解(meta-annotation): 可自定义注解 @Target:描述注解的使用范围,传入value参数指定 @Retention:描述注解的生命周期,传入value参数指定 (runtime&gt;class&gt;sources) @Documented:是否生成注解在Javadoc...

    自定义注解:springboot+vue-限制接口调用

    前言 公司前端项目用的是vue,后端用的是Springboot。因为最近公司业务的原因,需要根据条件限制接口的调用。限制的条件是根据指定的key获取...1.元注解(meta-annotation) 元注解的作用就是负责注解其他注解,在java.

    java6.0源码-meta-utils:用于启用java8之前的1st-class-functions的注释处理器

    java6.0源码用于启用 java8 之前的 1st-class-functions ...[](AnnotationProcessing.png) 项目属性 -&gt; Java Compiler -&gt; Annotation Processing -&gt; Factory Path: 启用项目特定设置 添加 JARs... 并选择

    Annotation注解的介绍和使用

    1.Annotation注解的介绍和使用

    spring-framework-reference4.1.4

    Not Using Commons Logging ................................................................... 12 Using SLF4J ..............................................................................................

    spring-framework-reference-4.1.2

    Not Using Commons Logging ................................................................... 12 Using SLF4J ..............................................................................................

    javax.annotation.jar文件

    spring 注解初始化,初始化开始@postconstruct 对象销毁@predestroy javax.annotation.jar文件

    apt-mirror-api-0.1.jar

    Files contained in apt-mirror-api-0.1.jar:...META-INF/MANIFEST.MF META-INF/maven/com.moparisthebest.aptIn16/apt-mirror-api/pom.properties META-INF/maven/com.moparisthebest.aptIn16/apt-mirror-api/pom.xml ...

    android 混淆出错 Can't process class 解决办法

    android 混淆出错 Can't process class 解决办法

    annotation_example

    注解_范例安装gradle 我们需要它来更方便地使用依赖项我们有2个模块注解...-&gt; DirectoryContent选择additional_files 现在我们收集jar文件: Build -&gt; Build Artifacts jar文件里面必须具有以下结构: META-INFcom./M

    springboot 基础简易实例, maven项目

    meta charset="UTF-8"&gt; &lt;title&gt;Insert title here&lt;/title&gt; &lt;/head&gt; &lt;body&gt; aaaaaaaaaaaaaaaaaaaaaaacccccccccccccc ${hello}"&gt;dddd &lt;/body&gt; &lt;/html&gt; ---------------------...

    TopLink_Mysql例子

    toplink mysql5 开发工具:Eclipse3.3 for J2ee 简要过程(先导好mysqlJDBC包和toplink包,进mysql建好...1.新建pojo类,加入Annotation 2.在src目录下建META-INF目录,写好persistence.xml文件 3.写测试类 自动完成建表

    Annotation-of-biological-data

    Gen-蛋白质-WikiData脚本中的其他信息发现 ### Repo包含两个脚本: read_write_files.py 读取文件的脚本,其中包含必须找到的...kdsD,PP_0957,carbohydrate metabolic process,metal ion binding, smi_1464,smi_1464,,

    gradle-incap-helper:帮助程序库和注释处理器,用于构建增量注释处理器

    此库和注释处理器可帮助您生成META-INF描述符,并从处理器的getSupportedOptions()返回合适的值getSupportedOptions()如果它是动态的)。 用法 将incap库添加到您的编译时依赖项中,并将incap-processor到您的注释...

    EasyLite:一个数据库Orm框架,编译时生成代码

    EasyLite是什么? EasyLite是一个便于使用的编译时生成代码的Orm框架,它刚出生... annotationProcessor project(':easylite-complier') } 配置参数 //数据库名称 &lt;meta-data android:name="database" android:va

    doma:面向Java 8+的DAO数据库映射框架

    多玛 Doma 2是Java 8+的数据库访问框架。 Doma具有多种优势: 使用在编译时验证并生成源代码。 提供类型安全的Criteria API。 支持Kotlin。 使用称为“双向SQL”SQL模板。... Entityql entityql = new Entityql ...

    一个支持annotation的SSH整合示例项目

    │ │ │ │ └─META-INF │ │ │ │ MANIFEST.MF │ │ │ │ │ │ │ └─resources │ │ └─test │ │ ├─java │ │ │ └─com │ │ │ └─tr │ │ │ └─geda │ │ │ └─evm │ │ │ └─...

    spring-web-2.5.jar

    META-INF/MANIFEST.MF META-INF/license.txt org.springframework.remoting.caucho.BurlapClientInterceptor.class org.springframework.remoting.caucho.BurlapProxyFactoryBean.class org.springframework....

Global site tag (gtag.js) - Google Analytics