Java Annotation 及几个常用开源项目注解原理简析

来源:互联网 发布:一元云购app源码 编辑:程序博客网 时间:2024/05/10 23:09

Java Annotation 及几个常用开源项目注解原理简析
http://www.trinea.cn/android/java-annotation-android-open-source-analysis/
1. Java Annotation 及几个常用开源项目注解原理简析
不少开源库都用到了注解的方式来简化代码提高开发效率
本文简单介绍下 Annotation 示例、概念及作用、分类、自定义、解析,并对几个 Android 开源库 Annotation 原理进行简析。
PDF 版: Java Annotation.pdf, PPT 版:Java Annotation.pptx, Keynote 版:Java Annotation.key
 
一、Annotation 示例
Override Annotation
Java
@Override public void onCreate(Bundle savedInstanceState);
1
2
3
@Override
public void onCreate(Bundle savedInstanceState);
 
Retrofit Annotation
Java
@GET(“/users/{username}”) User getUser(@Path(“username”) String username);
1
2
3
@GET(“/users/{username}”)
User getUser(@Path(“username”) String username);
 
Butter Knife Annotation
Java
@InjectView(R.id.user) EditText username;
1
2
@InjectView(R.id.user) EditText username;
 
ActiveAndroid Annotation
Java
@Column(name = “Name”) public String name;
1
2
@Column(name = “Name”) public String name;
 
Retrofit 为符合 RESTful 规范的网络请求框架
Butter Knife 为 View 及事件等依赖注入框架
Active Android 为 ORM 框架
更多见:Android 开源项目汇总
 
二、Annotation 概念及作用
1 概念
An annotation is a form of metadata, that can be added to Java source code. Classes, methods, variables, parameters and packages may be annotated. Annotations have no direct effect on the operation of the code they annotate.
能够添加到 Java 源代码的语法元数据。类、方法、变量、参数、包都可以被注解,可用来将信息元数据与程序元素进行关联。Annotation 中文常译为“注解”
 
2 作用
a. 标记,用于告诉编译器一些信息
b. 编译时动态处理,如动态生成代码
c. 运行时动态处理,如得到注解信息
这里的三个作用实际对应着后面自定义 Annotation 时说的 @Retention 三种值分别表示的 Annotation
看看下面一段代码的运行结果是多少?
Java
public class Person { private int id; private String name; public Person(int id, String name) { this.id = id; this.name = name; } public boolean equals(Person person) { return person.id == id; } public int hashCode() { return id; } public static void main(String[] args) { Set set = new HashSet(); for (int i = 0; i < 10; i++) { set.add(new Person(1, “Jim”)); } System.out.println(set.size()); } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class Person {
 
    private int    id;
    private String name;
 
    public Person(int id, String name) {
        this.id = id;
        this.name = name;
    }
 
    public boolean equals(Person person) {
        return person.id == id;
    }
 
    public int hashCode() {
        return id;
    }
 
    public static void main(String[] args) {
 
        Set set = new HashSet();
        for (int i = 0; i < 10; i++) {
            set.add(new Person(1, “Jim”));
        }
        System.out.println(set.size());
    }
}
 
答案见本文最后
 
三、Annotation 分类
1 标准 Annotation
包括Override, Deprecated, SuppressWarnings,标准 Annotation 是指 Java 自带的几个 Annotation,上面三个分别表示重写函数,函数已经被禁止使用,忽略某项 Warning
2 元 Annotation
@Retention, @Target, @Inherited, @Documented,元 Annotation 是指用来定义 Annotation 的 Annotation,在后面 Annotation 自定义部分会详细介绍含义
3 自定义 Annotation
自定义 Annotation 表示自己根据需要定义的 Annotation,定义时需要用到上面的元 Annotation
这里只是一种分类而已,也可以根据作用域分为源码时、编译时、运行时 Annotation,后面在自定义 Annotation 时会具体介绍
 
四、Annotation 自定义
1 调用
Java
public class App { @MethodInfo( author = “trinea.cn+android@gmail.com”, date = “2014/02/14”, version = 2) public String getAppName() { return “trinea”; } }
1
2
3
4
5
6
7
8
9
10
11
public class App {
 
    @MethodInfo(
        author = “trinea.cn+android@gmail.com”,
        date = “2014/02/14”,
        version = 2)
    public String getAppName() {
        return “trinea”;
    }
}
 
这里是调用自定义 Annotation——MethodInfo 的示例,MethodInfo Annotation 作用为给方法添加相关信息,包括 author、date、version
 
2 定义
Java
@Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @Inherited public @interface MethodInfo { String author() default “trinea@gmail.com”; String date(); int version() default 1; }
1
2
3
4
5
6
7
8
9
10
11
12
13
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Inherited
public @interface MethodInfo {
 
    String author() default “trinea@gmail.com”;
 
    String date();
 
    int version() default 1;
}
 
这里是 MethodInfo 的实现部分
(1). 通过 @interface 定义,注解名即为自定义注解名
(2). 注解配置参数名为注解类的方法名,且:
a. 所有方法没有方法体,没有参数没有修饰符,实际只允许 public & abstract 修饰符,默认为 public ,不允许抛异常
b. 方法返回值只能是基本类型,String, Class, annotation, enumeration 或者是他们的一维数组
c. 若只有一个默认属性,可直接用 value() 函数。一个属性都没有表示该 Annotation 为 Mark Annotation
(3). 可以加 default 表示默认值
 
3 元 Annotation
@Documented 是否会保存到 Javadoc 文档中
@Retention 保留时间,可选值 SOURCE(源码时),CLASS(编译时),RUNTIME(运行时),默认为 CLASS,值为 SOURCE 大都为 Mark Annotation,这类 Annotation 大都用来校验,比如 Override, Deprecated, SuppressWarnings
@Target 可以用来修饰哪些程序元素,如 TYPE, METHOD, CONSTRUCTOR, FIELD, PARAMETER 等,未标注则表示可修饰所有
@Inherited 是否可以被继承,默认为 false
 
五、Annotation 解析
1 运行时 Annotation 解析
(1) 运行时 Annotation 指 @Retention 为 RUNTIME 的 Annotation,可手动调用下面常用 API 解析
Java
method.getAnnotation(AnnotationName.class); method.getAnnotations(); method.isAnnotationPresent(AnnotationName.class);
1
2
3
4
method.getAnnotation(AnnotationName.class);
method.getAnnotations();
method.isAnnotationPresent(AnnotationName.class);
 
其他 @Target 如 Field,Class 方法类似
getAnnotation(AnnotationName.class) 表示得到该 Target 某个 Annotation 的信息,因为一个 Target 可以被多个 Annotation 修饰
getAnnotations() 则表示得到该 Target 所有 Annotation
isAnnotationPresent(AnnotationName.class) 表示该 Target 是否被某个 Annotation 修饰
(2) 解析示例如下:
Java
public static void main(String[] args) { try { Class cls = Class.forName(“cn.trinea.java.test.annotation.App”); for (Method method : cls.getMethods()) { MethodInfo methodInfo = method.getAnnotation( MethodInfo.class); if (methodInfo != null) { System.out.println(“method name:” + method.getName()); System.out.println(“method author:” + methodInfo.author()); System.out.println(“method version:” + methodInfo.version()); System.out.println(“method date:” + methodInfo.date()); } } } catch (ClassNotFoundException e) { e.printStackTrace(); } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public static void main(String[] args) {
    try {
        Class cls = Class.forName(“cn.trinea.java.test.annotation.App”);
        for (Method method : cls.getMethods()) {
            MethodInfo methodInfo = method.getAnnotation(
MethodInfo.class);
            if (methodInfo != null) {
                System.out.println(“method name:” + method.getName());
                System.out.println(“method author:” + methodInfo.author());
                System.out.println(“method version:” + methodInfo.version());
                System.out.println(“method date:” + methodInfo.date());
            }
        }
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
}
 
以之前自定义的 MethodInfo 为例,利用 Target(这里是 Method)getAnnotation 函数得到 Annotation 信息,然后就可以调用 Annotation 的方法得到响应属性值
 
2 编译时 Annotation 解析
(1) 编译时 Annotation 指 @Retention 为 CLASS 的 Annotation,甴 apt(Annotation Processing Tool) 解析自动解析。需要做的
a. 自定义类集成自 AbstractProcessor
b. 重写其中的 process 函数
这块很多同学不理解,实际是 apt(Annotation Processing Tool) 在编译时自动查找所有继承自 AbstractProcessor 的类,然后调用他们的 process 方法去处理
(2) 假设之前自定义的 MethodInfo 的 @Retention 为 CLASS,解析示例如下:
Java
@SupportedAnnotationTypes({ “cn.trinea.java.test.annotation.MethodInfo” }) public class MethodInfoProcessor extends AbstractProcessor { @Override public boolean process(Set

0 0
原创粉丝点击