java注解及在butternife中的实践和原理

1.  背景

之前去一个公司,说到了java的注解,问java的注解有几种方式,然后我提到了android中的butternife和afinal注解工具,我们知道butternife在6.1版本的时候还是InjectView,可以到7.1的时候用的却是BInd,这里面有什么区别吗。简单的说,InjectView是在运行的时间进行注解,而BInd在android安装的时候就执行了,肯定后者的执行效率更高些。

接下来说说java的注解吧。

2.  什么是注解

我们有必要对JDK 5.0新增的注解(Annotation)技术进行简单的学习,因为spring 支持@AspectJ,而@AspectJ本身就是基于JDK
5.0的注解技术。所以学习JDK 5.0的注解知识有助于我们更好地理解和掌握Spring的AOP技术。

对于Java开发人员来说,在编写代码时,除了源程序以外,我们还会使用Javadoc标签对类、方法或成员变量进行注释,以便使用Javadoc工具生成和源代码配套的Javadoc文档。这些@param、@return等Javadoc标签就是注解标签,它们为第三方工具提供了描述程序代码的注释信息。使用过Xdoclet的朋友,对此将更有感触,像Struts、hibernate都提供了Xdoclet标签,使用它们可以快速地生成对应程序代码的配置文件。

JDK5.0注解可以看成是Javadoc标签和Xdoclet标签的延伸和发展。在JDK5.0中,我们可以自定义这些标签,并通过Java语言的反射机制中获取类中标注的注解,完成特定的功能。

注解是代码的附属信息,它遵循一个基本原则:注解不能直接干扰程序代码的运行,无论增加或删除注解,代码都能够正常运行。Java语言解释器会忽略这些注解,而由第三方工具负责对注解进行处理。第三方工具可以利用代码中的注解间接控制程序代码的运行,它们通过Java反射机制读取注解的信息,并根据这些信息更改目标程序的逻辑,而这正是Spring AOP对@AspectJ提供支持所采取的方法。

注解的语法比较简单,除了@符号的使用以外,它基本上与java的固有语法一致,java内置了三种注解,定义在java.lang包中。

@Override:只能用在方法之上的,用来告诉别人这一个方法是改写父类的。

@Deprecated:建议别人不要使用旧的API的时候用的,编译的时候会用产生警告信息,可以设定在程序里的所有的元素上。

@SuppressWarnings:表示关闭一些不当的编译器警告信息。

附上java5.0版本的注解

public enum RetentionPolicy {
    /**
     * Annotation is only available in the source code.
     */
    SOURCE,
    /**
     * Annotation is available in the source code and in the class file, but not
     * at runtime. This is the default policy.
     */
    CLASS,
    /**
     * Annotation is available in the source code, the class file and is
     * available at runtime.
     */
    RUNTIME
}

我们看Butternife的注解view的代码

@Retention(RetentionPolicy.CLASS)
@Target({ElementType.FIELD})
public @interface InjectView {
    int value();
}

3.  定义注解

下面是一个定义注解的实例。

@Target(ElementType.TYPE)

@Retention(RetentionPolicy.RUNTIME)

@Documented

@Inherited

public @interface Description {

String value();

}

现在的IDE已经为我们提供了新建的入口,注解的格式是 public+@interface+名字。

所有的注解类都隐式继承于java.lang.annotation.Annotation,注解不允许显式继承于其他的接口。

一个注解可以拥有多个成员,成员声明和接口方法声明类似,这里,我们仅定义了一个成员,成员的声明有以下几点限制:

a)   成员以无入参无抛出异常的方式声明,如boolean value(String str)、boolean value() throws Exception等方式是非法的;

b)   可以通过default为成员指定一个默认值,如String level() default "LOW_LEVEL"、int high() default 2是合法的,当然也可以不指定默认值;

c)   成员类型是受限的,合法的类型包括原始类型及其封装类、String、Class、enums、注解类型,以及上述类型的数组类型。如ForumService value()、List foo()是非法的。

d)   如果注解只有一个成员,则成员名必须取名为value(),在使用时可以忽略成员名和赋值号(=),如@Description("使用注解的实例")。注解类拥有多个成员时,如果仅对value成员进行赋值则也可不使用赋值号,如果同时对多个成员进行赋值,则必须使用赋值号,如@DeclareParents
(value = "NaiveWaiter", defaultImpl = SmartSeller.class)。

e)   注解类可以没有成员,没有成员的注解称为标识注解,解释程序以标识注解存在与否进行相应的处理;

注解定义包含四个元注解,分别为@Target,@Retention,@Documented,@Inherited。各元注解的作用如下:

1)  @Target

表示该注解用于什么地方,可能的 ElemenetType 参数包括:

?  ElemenetType.CONSTRUCTOR 构造器声明。

?  ElemenetType.FIELD 域声明(包括 enum 实例)。

?  ElemenetType.LOCAL_VARIABLE 局部变量声明。

?  ElemenetType.METHOD 方法声明。

?  ElemenetType.PACKAGE 包声明。

?  ElemenetType.PARAMETER 参数声明。

?  ElemenetType.TYPE 类,接口(包括注解类型)或enum声明。

2)  @Retention

表示在什么级别保存该注解信息。可选的 RetentionPolicy 参数包括:

?  RetentionPolicy.SOURCE 注解将被编译器丢弃。

?  RetentionPolicy.CLASS 注解在class文件中可用,但会被VM丢弃。

?  RetentionPolicy.RUNTIME VM将在运行期也保留注释,因此可以通过反射机制读取注解的信息。

举一个例子,如@Override里面的Retention设为SOURCE,编译成功了就不要这一些检查的信息,相反,@Deprecated里面的Retention设为RUNTIME,表示除了在编译时会警告我们使用了哪个被Deprecated的方法,在执行的时候也可以查出该方法是否被Deprecated。

3)  @Documented

将此注解包含在 javadoc 中

4)  @Inherited

允许子类继承父类中的注解

4.  使用

@Description(value="使用注解的实例")

public class TestAnnotation {

}

使用注解的语法:@<注解名>(<成员名1>=<成员值1>,<成员名1>=<成员值1>,...)

如果成员是数组类型,可以通过{}进行赋值,用过butternife的就应该知道。如:

@AnnoExample(id= 2868724, synopsis = "Enable time-travel",
engineer = "Mr. Peabody")

public class ParseAnnotation {
   public static void main(String[] args) {
	   Class cls=null;
	try {
		cls = Class.forName("cn.java.Description");
		Method[] method = cls.getMethods();
		if(cls.isAnnotationPresent(Description.class)){
			  // 根据注解类型返回指定类型的注解
			   Description des = (Description)cls.getAnnotation(Description.class);
			   System.out.println("注解描述:" + des.value());

		}
	} catch (ClassNotFoundException e) {
		e.printStackTrace();
	}
}

输出结果如下:

注解描述:使用注解的实例

在JDK5.0里,Package、Class、Constructor、Method以及Field等反射对象都新增了访问注解信息的方法:<T extends Annotation>T getAnnotation(Class<T> annotationClass),该方法支持通过泛型直接返回注解对象。

时间: 2024-11-05 05:04:53

java注解及在butternife中的实践和原理的相关文章

attilax.java 注解的本质and 使用最佳实践(3)O7

attilax.java 注解的本质and 使用最佳实践(3)O7 1. 定义pojo 1 2. 建立注解By eclipse tps 1 3. 注解参数的可支持数据类型: 2 4. 注解处理器 2 5. 读取注解 2 6. 不能读取到注解,为null的解决 3 7. 参考: 3 1. 定义pojo public class pojo { @Validate("required") String name; int id; @Validate("required")

JAVA注解在SSH开发中的简单应用

在系统开发过程中,出现错误在所难免.虽然系统出错时控制台也会报错,但是因为系统控制台输出太多,往往不能快速定位出现错误的功能点及原因.在此通过使用注解,结合spring的AOP,来制作一个错误输出拦截器. 首先写一个注解类Catcher: @Target({ ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited public @interface Catcher {     String 

java注解例子

java注解在web框架中使用比较广泛,这使得对象之间的关系配置起来更加容易 目前web框架中最常用的两种配置对象依赖关系的方式就是注解和xml配置文件的方法,api配置相对来说用的少一些, 下面实现一个Table注解来实现数据库表和实体bean之间的对应关系,实现一个Column注解来实现数据库表中每个字段和实体bean每个属性之间的 对应关系.java中的orm基本上就是根据这种思想来实现的. Table注解代码: package com.panther.dong.annotation.an

Java注解介绍

原文链接: Java Annotations: An Introduction原文日期: 2005年10月14日翻译日期: 2014年07月20日翻译人员: 铁锚 翻译完后,感觉这篇文章是不是在http://www.developer.com被挖坟了? Java注解介绍 基于注解(Annotation-based)的Java开发无疑是最新的开发趋势.[译者注: 这是05年的文章,在2014年,毫无疑问,多人合作的开发,使用注解变成很好的合作方式,相互之间的影响和耦合可以很低]. 基于注解的开发将

Java注解实践

Java注解实践 注解对代码的语意没有直接影响, 他们只负责提供信息给相关的程序使用. 注解永远不会改变被注解代码的含义, 但可以通过工具对被注解的代码进行特殊处理. JDK 基本Annotation 注解 说明 @Override 重写 @Deprecated 已过时 @SuppressWarnings(value = "unchecked") 压制编辑器警告 @SafeVarargs 修饰"堆污染"警告 @FunctionalInterface Java8特有的

java注解中的元注解

一:java注解中的元注解 四个元注解分别是:@Target,@Retention,@Documented,@Inherited , 再次强调下元注解是java API提供,是专门用来定义注解的注解,其作用分别如下: @Target 表示该注解用于什么地方,可能的值在枚举类 ElemenetType 中,包括: ElemenetType.CONSTRUCTOR----------------------------构造器声明 ElemenetType.FIELD ----------------

Java注解(二) 系统注解

上一篇博文讲了Java注解是什么.有什么作用.现在让我们来谈谈Java本身提供的一些注解,包括内置注解跟元注解(后面解释). 概要 系统注解 内置注解 @Deprecated @Override @SuppressWarnings 元注解 @Retention @Target @Inherited @Documented 内置注解 Java本身提供了一些比较常用的注解,下面就分别介绍一下@Deprecated.@Override.@SuppressWarnings. @Deprecated 作用

JAVA 注解的几大作用及使用方法详解

JAVA 注解的几大作用及使用方法详解 (2013-01-22 15:13:04) 转载▼ 标签: java 注解 杂谈 分类: Java java 注解,从名字上看是注释,解释.但功能却不仅仅是注释那么简单.注解(Annotation) 为我们在代码中添加信息提供了一种形式化的方法,是我们可以在稍后 某个时刻方便地使用这些数据(通过 解析注解 来使用这些数据),常见的作用有以下几种: 1.生成文档.这是最常见的,也是java 最早提供的注解.常用的有@see @param @return 等:

Java 注解(Annotation)概念及实战

摘要: java注解:java 提供了一种源程序中的 元素 关联任何信息和任何元数据的途径和方法. 学习注解的目的: 能够读懂别人写的代码,特别是框架相关的代码 让编程更加简洁,代码更加清晰 让别人高看一眼,特别是会使用自定义注解 目录: java中的常见注解 注解分类 自定义注解 注解应用实践 1. java中的常见注解 1) JDK 自带的注解 @Override @Deprecated @SuppressWarnings2) 常见的第三方注解 Spring @Autowired @Serv