[Java]Annotation元数据的几个应用||Java使用Annotation实现I18N

Tiger出笼以后, Annotation成了一个小小的亮点,虽然有抄袭.net之嫌疑,毕竟让Java开发者方便了许多。EJB3.0和Hibernate Annotation版都是基于这个东西了。下面是结合Spring的自动Log/鉴权/国际化应用:

public interface SessionService extends Service {
    @Anonymous //允许未登录用户调用
    @OperationLog //自动log
    @Name(zh = “登录”)
    public String login(
            @Name(en=”user”,zh = “用户”)String user,
            @OperationLog(false)String password); //不log密码

    @OperationLog
    @Name(zh=”注销”)
    public void logout();

@Anonymous用于鉴权,允许匿名访问。通过ThreadLocal的变量保存当前用户的Session信息。
@OperationLog 用于标记是否自动Log, 可以作用于类、方法、参数
@Name用于i18n国际化支持。Java里面常见的国际化解决方法是.properties文件,个人认为这个方案不好,适合大型项目开发。小项目中这个标记一下足矣。如果要添加一种语言,只要在@Name中多一个参数,利用Eclipse的reference很容易知道有哪些地方要翻译。

同样@Name还可以加在Bean上,自动构造多语言的Table/List,方便之极。

@Name(zh=”安全事件”,en=”Security Event”)
public class SecurityEvent extends AbstractEmsEvent{
    String cause;
    @Name(zh=”原因”)
    public String getCause() {
        return cause;
    }
    
}

附上我的I18nUtil工具类:

/**
 * @author steeven
 */
public class I18nUtil {
    public static String getName(Method method) {
        return getI18n(method,Name.class);
    }
    public static String getTip(Method method) {
        return getI18n(method,Tip.class);
    }
    public static String getI18n(Method method,Class<? extends Annotation> i18nClass) {
        Annotation i18n = method.getAnnotation(i18nClass);
        return getProperty(i18n,method.getName());
    }

    public static String getProperty(Annotation i18n, String defaultValue) {
        if (i18n==null)
            return defaultValue;
        Class<? extends Annotation> clz = i18n.annotationType();
        try {
            Method method = clz.getMethod(getI18nMethodName());
            assert method!=null;
            String r = (String) method.invoke(i18n);
            return r==null || r.length()==0?defaultValue:r;
        } catch (Exception e) {
            assert false;
            return defaultValue;
        }
    }

    private static String getI18nMethodName() {
        return Locale.getDefault().getLanguage();
    }

    @SuppressWarnings(“unchecked”)
    public static <T extends Annotation> T getAnnotation(Annotation[] argAnnotations, Class<T> clz) {
        for(Annotation anno:argAnnotations)
            if (clz.isInstance(anno))
                return (T) anno;
        return null;
    }
}

元数据的结构似乎有些简单,有时候要加很多@Name,@Tip,@Help好像没办法一个Tag搞定。

另外,还可以通过Annotation加上验证、输入界面描述,等等。程序很容易自动化,再多的画面也用不了多少代码。

Jdk5.0提供了这么好用的原数据机制,你有什么好的用法呢?

From: http://www.cnblogs.com/steeven/archive/2005/07/28/201684.html

@SuppressWarnings是什么意思?

J2SE 提供的最后一个批注是 @SuppressWarnings。该批注的作用是给编译器一条指令,告诉它对被批注的代码元素内部的某些警告保持静默。 

@SuppressWarnings 批注允许您选择性地取消特定代码段(即,类或方法)中的警告。其中的想法是当您看到警告时,您将调查它,如果您确定它不是问题,您就可以添加一个 @SuppressWarnings 批注,以使您不会再看到警告。虽然它听起来似乎会屏蔽潜在的错误,但实际上它将提高代码安全性,因为它将防止您对警告无动于衷 — 您看到的每一个警告都将值得注意。

java自定义注解

Java注解是附加在代码中的一些元信息,用于一些工具在编译、运行时进行解析和使用,起到说明、配置的功能。
注解不会也不能影响代码的实际逻辑,仅仅起到辅助性的作用。包含在 java.lang.annotation 包中。

1、元注解

元注解是指注解的注解。包括  @Retention @Target @Document @Inherited四种。
1.1、@Retention: 定义注解的保留策略

@Retention(RetentionPolicy.SOURCE)   //注解仅存在于源码中,在class字节码文件中不包含
@Retention(RetentionPolicy.CLASS)     // 默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得,
@Retention(RetentionPolicy.RUNTIME)  // 注解会在class字节码文件中存在,在运行时可以通过反射获取到
1.2、@Target:定义注解的作用目标
其定义的源码为:
复制代码
1 @Documented
2 @Retention(RetentionPolicy.RUNTIME)
3 @Target(ElementType.ANNOTATION_TYPE)
4 public @interface Target {
5     ElementType[] value();
6 }
复制代码

@Target(ElementType.TYPE)   //接口、类、枚举、注解

@Target(ElementType.FIELD) //字段、枚举的常量
@Target(ElementType.METHOD) //方法
@Target(ElementType.PARAMETER) //方法参数
@Target(ElementType.CONSTRUCTOR)  //构造函数
@Target(ElementType.LOCAL_VARIABLE)//局部变量
@Target(ElementType.ANNOTATION_TYPE)//注解
@Target(ElementType.PACKAGE) ///包
 由以上的源码可以知道,他的elementType 可以有多个,一个注解可以为类的,方法的,字段的等等
1.3、@Document:说明该注解将被包含在javadoc中
1.4、@Inherited:说明子类可以继承父类中的该注解
2、java 注解的自定义
      下面是自定义注解的一个例子
复制代码
@Documented
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Yts {
    public enum YtsType{util,entity,service,model};
   public YtsType classType() default YtsType.util;
}
复制代码

 

复制代码
1 @Documented
2 @Retention(RetentionPolicy.RUNTIME)
3 @Target(ElementType.METHOD)
4 @Inherited
5 public @interface HelloWorld {
6    public String name()default "";
7 }
复制代码

 

@Retention(RetentionPolicy.RUNTIME)

定义的这个注解是注解会在class字节码文件中存在,在运行时可以通过反射获取到。

@Target({ElementType.TYPE,ElementType.METHOD})

因此这个注解可以是类注解,也可以是方法的注解

这样一个注解就自定义好了,当然注解里面的成员可以为基本的数据类型,也可以为数据,Object等等

 

3 注解是定义好了,那么怎么来得到,解析注解呢?

java的反射机制可以帮助,得到注解,代码如下:

复制代码
 1 public class ParseAnnotation {
 2 
 3      public void parseMethod(Class clazz) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, SecurityException, NoSuchMethodException, InstantiationException{
 4   Object obj = clazz.getConstructor(new Class[]{}).newInstance(new Object[]{});
 5     for(Method method : clazz.getDeclaredMethods()){
 6         HelloWorld say = method.getAnnotation(HelloWorld.class);
 7         String name = "";
 8         if(say != null){
 9            name = say.name();
10            method.invoke(obj, name);
11         }
12        Yts yts = (Yts)method.getAnnotation(Yts.class);
13        if(yts != null){
14           if(YtsType.util.equals(yts.classType())){
15           System.out.println("this is a util method");
16         }else{
17             System.out.println("this is a other method");
18             }
19         }
20       }
21     }
22     @SuppressWarnings("unchecked")
23     public void parseType(Class clazz) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException{
24         Yts yts = (Yts) clazz.getAnnotation(Yts.class);
25         if(yts != null){
26             if(YtsType.util.equals(yts.classType())){
27                 System.out.println("this is a util class");
28             }else{
29                 System.out.println("this is a other class");
30             }
31         }
32     }
33     
34 }
复制代码

 

前一个方法是解析得到方法注解的,后一个方法是得到类注解的

以下是测试方法类

复制代码
 1 @Yts(classType =YtsType.util)
 2 public class SayHell {
 3 
 4     @HelloWorld(name = " 小明 ")
 5     @Yts
 6     public void sayHello(String name){
 7         if(name == null || name.equals("")){
 8             System.out.println("hello world!");
 9         }else{
10             System.out.println(name + "say hello world!");
11         }
12     }
13 }
复制代码

 

 

复制代码
1 public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, SecurityException, NoSuchMethodException, InstantiationException {
2         ParseAnnotation parse = new ParseAnnotation();
3         parse.parseMethod(SayHell.class);
4         parse.parseType(SayHell.class);
5     }
复制代码

http://blog.csdn.net/yixiaogang109/article/details/7328466

 

 

1、Annotation的工作原理:

JDK5.0中提供了注解的功能,允许开发者定义和使用自己的注解类型。该功能由一个定义注解类型的语法和描述一个注解声明的语法,读取注解的API,一个使用注解修饰的class文件和一个注解处理工具组成。

Annotation并不直接影响代码的语义,但是他可以被看做是程序的工具或者类库。它会反过来对正在运行的程序语义有所影响。

Annotation可以冲源文件、class文件或者在运行时通过反射机制多种方式被读取。

2、@Override注解:
java.lang
注释类型 Override
@Target(value=METHOD)
@Retention(value=SOURCE)
public @interface Override

表示一个方法声明打算重写超类中的另一个方法声明。如果方法利用此注释类型进行注解但没有重写超类方法,则编译器会生成一条错误消息。

@Override注解表示子类要重写父类的对应方法。

Override是一个Marker annotation,用于标识的Annotation,Annotation名称本身表示了要给工具程序的信息。

下面是一个使用@Override注解的例子:

class A {
    private String id;
    A(String id){
        this.id = id;
    }
    @Override
    public String toString() {
        return id;
    }
}
3、@Deprecated注解:
java.lang
注释类型 Deprecated
@Documented
@Retention(value=RUNTIME)
public @interface Deprecated

用 @Deprecated 注释的程序元素,不鼓励程序员使用这样的元素,通常是因为它很危险或存在更好的选择。在使用不被赞成的程序元素或在不被赞成的代码中执行重写时,编译器会发出警告。

@Deprecated注解表示方法是不被建议使用的。

Deprecated是一个Marker annotation。

下面是一个使用@Deprecated注解的例子:

class A {
    private String id;
    A(String id){
        this.id = id;
    }
    @Deprecated
    public void execute(){
        System.out.println(id);
    }
    public static void main(String[] args) {
        A a = new A("a123");
        a.execute();
    }
}
4、@SuppressWarnings注解:
java.lang
注释类型 SuppressWarnings
@Target(value={TYPE,FIELD,METHOD,PARAMETER,CONSTRUCTOR,LOCAL_VARIABLE})
@Retention(value=SOURCE)
public @interface SuppressWarnings

指示应该在注释元素(以及包含在该注释元素中的所有程序元素)中取消显示指定的编译器警告。注意,在给定元素中取消显示的警告集是所有包含元素中取消显示的警告的超集。例如,如果注释一个类来取消显示某个警告,同时注释一个方法来取消显示另一个警告,那么将在此方法中同时取消显示这两个警告。

根据风格不同,程序员应该始终在最里层的嵌套元素上使用此注释,在那里使用才有效。如果要在特定的方法中取消显示某个警告,则应该注释该方法而不是注释它的类。

@SuppressWarnings注解表示抑制警告。

下面是一个使用@SuppressWarnings注解的例子:

@SuppressWarnings("unchecked")
public static void main(String[] args) {
    List list = new ArrayList();
    list.add("abc");
}
5、自定义注解:

使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口,由编译程序自动完成其他细节。在定义注解时,不能继承其他的注解或接口。

自定义最简单的注解:

public @interface MyAnnotation {

}

使用自定义注解:

public class AnnotationTest2 {

    @MyAnnotation
    public void execute(){
        System.out.println("method");
    }
}
5.1、添加变量:
public @interface MyAnnotation {

    String value1();
}

使用自定义注解:

public class AnnotationTest2 {

    @MyAnnotation(value1="abc")
    public void execute(){
        System.out.println("method");
    }
}

当注解中使用的属性名为value时,对其赋值时可以不指定属性的名称而直接写上属性值接口;除了value意外的变量名都需要使用name=value的方式赋值。

5.2、添加默认值:
public @interface MyAnnotation {

    String value1() default "abc";
}
5.3、多变量使用枚举:
public @interface MyAnnotation {

    String value1() default "abc";
    MyEnum value2() default MyEnum.Sunny;
}
enum MyEnum{
    Sunny,Rainy
}

使用自定义注解:

public class AnnotationTest2 {

    @MyAnnotation(value1="a", value2=MyEnum.Sunny)
    public void execute(){
        System.out.println("method");
    }
}
5.4、数组变量:
public @interface MyAnnotation {

    String[] value1() default "abc";
}

使用自定义注解:

public class AnnotationTest2 {

    @MyAnnotation(value1={"a","b"})
    public void execute(){
        System.out.println("method");
    }
}
6、设置注解的作用范围:
@Documented
@Retention(value=RUNTIME)
@Target(value=ANNOTATION_TYPE)
public @interface Retention

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

只有元注释类型直接用于注释时,Target 元注释才有效。如果元注释类型用作另一种注释类型的成员,则无效。

public enum RetentionPolicy
extends Enum<RetentionPolicy>

注释保留策略。此枚举类型的常量描述保留注释的不同策略。它们与 Retention 元注释类型一起使用,以指定保留多长的注释。

CLASS
编译器将把注释记录在类文件中,但在运行时 VM 不需要保留注释。
RUNTIME
编译器将把注释记录在类文件中,在运行时 VM 将保留注释,因此可以反射性地读取。
SOURCE
编译器要丢弃的注释。

@Retention注解可以在定义注解时为编译程序提供注解的保留策略。

属于CLASS保留策略的注解有@SuppressWarnings,该注解信息不会存储于.class文件。

6.1、在自定义注解中的使用例子:
@Retention(RetentionPolicy.CLASS)
public @interface MyAnnotation {

    String[] value1() default "abc";
}
7、使用反射读取RUNTIME保留策略的Annotation信息的例子:
java.lang.reflect
        接口 AnnotatedElement
所有已知实现类:
        AccessibleObject, Class, Constructor, Field, Method, Package

表示目前正在此 VM 中运行的程序的一个已注释元素。该接口允许反射性地读取注释。由此接口中的方法返回的所有注释都是不可变并且可序列化的。调用者可以修改已赋值数组枚举成员的访问器返回的数组;这不会对其他调用者返回的数组产生任何影响。

如果此接口中的方法返回的注释(直接或间接地)包含一个已赋值的 Class 成员,该成员引用了一个在此 VM 中不可访问的类,则试图通过在返回的注释上调用相关的类返回的方法来读取该类,将导致一个 TypeNotPresentException。

isAnnotationPresent
boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)

如果指定类型的注释存在于此元素上,则返回 true,否则返回 false。此方法主要是为了便于访问标记注释而设计的。

参数:

annotationClass – 对应于注释类型的 Class 对象

返回:

如果指定注释类型的注释存在于此对象上,则返回 true,否则返回 false

抛出:

NullPointerException – 如果给定的注释类为 null

从以下版本开始:

1.5

getAnnotation
<T extends Annotation> T getAnnotation(Class<T> annotationClass)

如果存在该元素的指定类型的注释,则返回这些注释,否则返回 null。

参数:

annotationClass – 对应于注释类型的 Class 对象

返回:

如果该元素的指定注释类型的注释存在于此对象上,则返回这些注释,否则返回 null

抛出:

NullPointerException – 如果给定的注释类为 null

从以下版本开始:

1.5

getAnnotations
Annotation[] getAnnotations()

返回此元素上存在的所有注释。(如果此元素没有注释,则返回长度为零的数组。)该方法的调用者可以随意修改返回的数组;这不会对其他调用者返回的数组产生任何影响。

返回:

此元素上存在的所有注释

从以下版本开始:

1.5

getDeclaredAnnotations
Annotation[] getDeclaredAnnotations()

返回直接存在于此元素上的所有注释。与此接口中的其他方法不同,该方法将忽略继承的注释。(如果没有注释直接存在于此元素上,则返回长度为零的一个数组。)该方法的调用者可以随意修改返回的数组;这不会对其他调用者返回的数组产生任何影响。

返回:

直接存在于此元素上的所有注释

从以下版本开始:

1.5


下面是使用反射读取RUNTIME保留策略的Annotation信息的例子:

自定义注解:

@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {

    String[] value1() default "abc";
}

使用自定义注解:

public class AnnotationTest2 {

    @MyAnnotation(value1={"a","b"})
    @Deprecated
    public void execute(){
        System.out.println("method");
    }
}

读取注解中的信息:

public static void main(String[] args) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
    AnnotationTest2 annotationTest2 = new AnnotationTest2();
    //获取AnnotationTest2的Class实例
    Class<AnnotationTest2> c = AnnotationTest2.class;
    //获取需要处理的方法Method实例
    Method method = c.getMethod("execute", new Class[]{});
    //判断该方法是否包含MyAnnotation注解
    if(method.isAnnotationPresent(MyAnnotation.class)){
        //获取该方法的MyAnnotation注解实例
        MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class);
        //执行该方法
        method.invoke(annotationTest2, new Object[]{});
        //获取myAnnotation
        String[] value1 = myAnnotation.value1();
        System.out.println(value1[0]);
    }
    //获取方法上的所有注解
    Annotation[] annotations = method.getAnnotations();
    for(Annotation annotation : annotations){
        System.out.println(annotation);
    }
}
8、限定注解的使用:

限定注解使用@Target。

@Documented
@Retention(value=RUNTIME)
@Target(value=ANNOTATION_TYPE)
public @interface Target

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

@Target(ElementType.ANNOTATION_TYPE)
    public @interface MetaAnnotationType {
        ...
    }

此元注释指示该声明类型只可作为复杂注释类型声明中的成员类型使用。它不能直接用于注释:

@Target({}) 
    public @interface MemberType {
        ...
    }

这是一个编译时错误,它表明一个 ElementType 常量在 Target 注释中出现了不只一次。例如,以下元注释是非法的:

@Target({ElementType.FIELD, ElementType.METHOD, ElementType.FIELD})
    public @interface Bogus {
        ...
    }
public enum ElementType
extends Enum<ElementType>

程序元素类型。此枚举类型的常量提供了 Java 程序中声明的元素的简单分类。

这些常量与 Target 元注释类型一起使用,以指定在什么情况下使用注释类型是合法的。

ANNOTATION_TYPE
注释类型声明
CONSTRUCTOR
构造方法声明
FIELD
字段声明(包括枚举常量)
LOCAL_VARIABLE
局部变量声明
METHOD
方法声明
PACKAGE
包声明
PARAMETER
参数声明
TYPE
类、接口(包括注释类型)或枚举声明


注解的使用限定的例子:

@Target(ElementType.METHOD)
public @interface MyAnnotation {

    String[] value1() default "abc";
}
9、在帮助文档中加入注解:

要想在制作JavaDoc文件的同时将注解信息加入到API文件中,可以使用java.lang.annotation.Documented。

在自定义注解中声明构建注解文档:

@Documented
public @interface MyAnnotation {

    String[] value1() default "abc";
}

使用自定义注解:

public class AnnotationTest2 {

    @MyAnnotation(value1={"a","b"})
    public void execute(){
        System.out.println("method");
    }
}
10、在注解中使用继承:

默认情况下注解并不会被继承到子类中,可以在自定义注解时加上java.lang.annotation.Inherited注解声明使用继承。

@Documented
@Retention(value=RUNTIME)
@Target(value=ANNOTATION_TYPE)
public @interface Inherited

指示注释类型被自动继承。如果在注释类型声明中存在 Inherited 元注释,并且用户在某一类声明中查询该注释类型,同时该类声明中没有此类型的注释,则将在该类的超类中自动查询该注释类型。此过程会重复进行,直到找到此类型的注释或到达了该类层次结构的顶层 (Object) 为止。如果没有超类具有该类型的注释,则查询将指示当前类没有这样的注释。

注意,如果使用注释类型注释类以外的任何事物,此元注释类型都是无效的。还要注意,此元注释仅促成从超类继承注释;对已实现接口的注释无效。

除了文章中有特别说明,均为IT宅原创文章,转载请以链接形式注明出处。
本文链接:http://www.itzhai.com/java-based-notebook-annotation-annotation-introduction-and-use-custom-annotations.html

Java @interface||Java自定义Annotation ||Java自定义注解

从jdk5.0开始支持Annotation(注解)。Annotation(注解)提供了一条与程序元素关联信息或者元数据(metadata)的途径。从某些方面看,annotation就像修饰符一样被使用,应用于包、类型、构造方法、方法、成员变量、参数、本地变量的声明中。这些信息被存储在annotation的类似map的“name=value”结构对中。 annotation类型是一种接口,能够通过java反射方式提供对其信息的访问。
至于用处我可以告诉你,他不会对你的程序代码产生任何影响。因为Annotation(注解)有着它自己的潜规则:规则就是不能影响程序代码的执行,无论增加、删除 annotation,代码都始终如一的执行。另外,尽管一些annotation通过java的反射api方法在运行时被访问,而java语言解释器在工作时忽略了这些annotation。正是由于java虚拟机忽略了annotation,导致了annotation类型在代码中是不起任何作用的;只有通过某种配套的工具才会对annotation类型中的信息进行访问和处理。换句话说就是你的程序代码有它没它都一样。
那么你会问要它还有什么用呢。呵呵!其实它对例如编译器警告或者像文档生成器等辅助工具会产生影响。我们可以用它来编写辅助工具。例如:编写一个annotation代码分析工具扫描源码中的annotation并调用我们定义好的annotation处理器完成我们所要完成的工作(比如验证函数的重载(@Override))。
@Override
public String toSting() {
//这里我声明了一个函数,要重载toString()方法,注意方法名拼写错了
//那么通过annotation扫描就会得知错误。
return “[” + super.toString() + “]”;
}

Java中的Annotation解析之一

在创建EJB组件时,必需提供一些定义,使得EJB组件使用一些服务例如:安全服务,持久化服务,事务服务。EJB容器可以提供这些服务,这样EJB只要实现业务逻辑就可以了。但是说到底EJB容器使用EJB组件的元数据来提供这些服务,在以前EJB的元数据是以XML配置文件形式出现的,这些配置文件与EJB源文件是分开的。

EJB的部署人员无法了解EJB本身的信息,如果EJB组件的创建者用注释(Annotation)的方法将这些配置服务的信息和代码放在一起,这样EJB的部署者就可以了解EJB的信息,EJB的home接口可以使用Annotation自动生成,当然到目前为止更好的是在简单的Java Object上使用Annotations。

一 什么是Annotation

在已经发布的JDK1.5(tiger)中增加新的特色叫 Annotation。Annotation提供一种机制,将程序的元素如:类,方法,属性,参数,本地变量,包和元数据联系起来。这样编译器可以将元数据存储在Class文件中。这样虚拟机和其它对象可以根据这些元数据来决定如何使用这些程序元素或改变它们的行为。

二 定义一个简单的Annotation并使用它

1.定义Annotation

定义一个Annotation是什么简单的,它采取的是类似于Interface的定义方式: “@+annotation类型名称+(..逗号分割的name-value对…)”

//Example 1
package sz.starbex.bill.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface SimpleAnnotation {
String value();
}

@Retention这个meta-annotation表示我们创建的SimpleAnnotation这个Annotation将会存储在Class文件中,并在java

VM运行时加载它。@Target这个meta-annotation表示我们创建的SimplwAnnotation将会为描述方法,而@interface SimpleAnnotation是我们自定义的Annotation,它有一个成员叫value,返回值是String。

2.使用Annotation

//Example 2
package sz.starbex.bill.annotation;
import sz.starbex.bill.annotation.SimpleAnnotation;
public class UsingSimpleAnnotation {
@SimpleAnnotation(value=”Pass:This method will Pass”)//注意name=value的用法
public void pass(){
if(10>5) System.out.println(“测试通过”);
}
@SimpleAnnotation(“Fail:This method will Fail”)//注意name=value的用法
public void fail(){
if(10<5) System.out.println(“测试失败”);
}
}

一个Annotation用于程序元素(在本例中是method),在method方法之前用(@Annotation名称(name=value,name=value…..)。在本例中是@SimpleAnnotation(value=”Pass:This method will Pass”)。每个annotation具有一个名字和成员个数>=0,当只有一个单一的成员时,这个成员就是value。我们也可以这样写 @SimpleAnnotation(“Fail:This method will Fail”)。至此@SimpleAnnotation将Pass和Fail联系起来了。

3.在运行时访问Annotation

一旦Annotation与程序元素联系起来,我们可以通过反射访问它们并可以取得它们的值。我们使用一个新的interface:java.lang.reflect.AnnotatedElement。java.lang.reflect.AnnotatedElement接口中的方法有:

  • a. boolean isAnnotationPresent(Class annotationType)
    如果指定类型的注释存在于此元素上,则返回 true,否则返回 false。
  • b. T getAnnotation(Class annotationType)
    如果存在该元素的指定类型的注释,则返回这些注释,否则返回 null。
  • c. Annotation[] getAnnotations()
    返回此元素上存在的所有注释。
  • d. Annotation[] getDeclaredAnnotations()
    返回直接存在于此元素上的所有注释。

你要注意 isAnnotationPresent和getAnnotation方法,它们使用了Generics,请参考我的Java 范型的Blog。

下面我们列出一些实现了AnnotatedElement 接口的类

1. java.lang.reflect.AccessibleObject
2. java.lang.Class
3. java.lang.reflect.Constructor
4. java.lang.reflect.Field
5. java.lang.reflect.Method
6. java.lang.Package

下面的Example程序说明了如何在运行环境访问Annotation

 

package sz.starbex.bill.annotation;
import sz.starbex.bill.annotation.SimpleAnnotation;
import java.lang.reflect.Method;
public class SimpleAccessAnnotation {
static void accessAnnotationTest(Class usingAnnnotationClass){
try {
//Object usingAnnnotationClass=Class.forName(usingAnnotationClassName).newInstance();
Method [] methods=usingAnnnotationClass.getDeclaredMethods();//取得对方法
for(Method method:methods){
System.out.println(method.getName());
SimpleAnnotation
simpleAnnotation=method.getAnnotation(SimpleAnnotation.class);//得到方法的Annotation
if(simpleAnnotation!=null){
System.out.print(simpleAnnotation.value()+”==”);
String result=invoke(method,usingAnnnotationClass);
System.out.println(result);
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
static String invoke(Method m, Object o) {
String result = “passed”;
try {
m.invoke(m,new Object[]{});
} catch (Exception e) {
// TODO Auto-generated catch block
result = “failed”;
}
return result;
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
accessAnnotationTest(UsingSimpleAnnotation.class);
}
}

以上是简单的简绍Annotation,让大家对Annotation有一个初步的了解,下面二会简绍Annotation的定义和语法。

作者:管斌(http://blog.matrix.org.cn/page/guanbing)
原文地址:http://www.matrix.org.cn/resource/article/44/44336_Java+Annotation.html

(责任编辑:铭铭 mingming_ky@126.com TEL:(010)68476636)