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),该方法支持通过泛型直接返回注解对象。

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

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

    attilax.java 注解的本质and 使用最佳实践(3)O7 1. 定义pojo 1 2. 建立注解By eclipse tps 1 3. 注解参数的可支持数据类型: 2 4. 注解处理器 2 ...

  2. 高级工程师-Java注解

    高级工程师-Java注解 前言 代码,就是我们身为程序员的名片. 简洁,优雅,统一,是我们的追求. 优秀的代码,会给浏览者一种艺术的美感.如DL大神的JUC包,感兴趣的小伙伴,可以研究一下. 那么日常 ...

  3. 必知必会之Java注解

    必知必会之Java注解 目录 不定期更新中-- 元注解 @Documented @Indexed @Retention @Target 常用注解 @Deprecated @FunctionalInte ...

  4. Java注解实践

    Java注解实践 标签 : Java基础 注解对代码的语意没有直接影响, 他们只负责提供信息给相关的程序使用. 注解永远不会改变被注解代码的含义, 但可以通过工具对被注解的代码进行特殊处理. JDK ...

  5. 如何在java注解中加入原生html标签内容

    你是否也遇到过类似的事情.想在java注解加入类似于下面这种注释: 结果出来却变成了这样 ,标签被解析了, 这怎么办呢 : 且看分解 我们在注解中直接放入下边这样的代码: <Response&g ...

  6. java自定义注解知识实例及SSH框架下,拦截器中无法获得java注解属性值的问题

    一.java自定义注解相关知识 注解这东西是java语言本身就带有的功能特点,于struts,hibernate,spring这三个框架无关.使用得当特别方便.基于注解的xml文件配置方式也受到人们的 ...

  7. java注解中的元注解

    一:java注解中的元注解 四个元注解分别是:@Target,@Retention,@Documented,@Inherited , 再次强调下元注解是java API提供,是专门用来定义注解的注解, ...

  8. 【Java】java注解@Transient的作用, 配合JPA中时间段的查询

    java注解@Transient的作用 @Transient标注的属性,不会被ORM框架映射到数据库中. 用于数据库表字段和java实体属性不一致的时候,标注在属性上使用. 例如时间段的查询 查询 R ...

  9. 夯实Java基础系列15:Java注解简介和最佳实践

    Java注解简介 注解如同标签 Java 注解概述 什么是注解? 注解的用处 注解的原理 元注解 JDK里的注解 注解处理器实战 不同类型的注解 类注解 方法注解 参数注解 变量注解 Java注解相关 ...

随机推荐

  1. ANT不完全总结,包含各种命令,ant例子等,转自:http://lavasoft.blog.51cto.com/62575/87306

    ANT不完全总结   好久没有用Ant了,最近让MyEclipse.JBuilder2008逼的重回Ant上了.手生了,写了一个脚本后,重新总结下.参考了官方的文档和网上一些资料.   一.ANT的介 ...

  2. Android自动打包工具aapt详解

    概念 在Android.mk中有LOCAL_AAPT_FLAGS配置项,在gradle中也有aaptOptions,那么aapt到底是干什么的呢? aapt即Android Asset Packagi ...

  3. PHP + JavaScript + Ajax 实现无刷新页面加载效果

    数据源工厂 Json生成方式1 Json生成方式2 数据搬运工 数据加工师 转换类型 加工展示 结果展示 初始页面 点击按钮之后 总结 今天这个实验的思路就是实现一个无刷新的页面加载效果.具体的思路是 ...

  4. 如何对n个大小都小于100的整数进行排序,要求时间复杂度O(n),空间复杂度O(1)。

    提示:hash表 #include <iostream> using namespace std; #define N 100 #define RANGE 100 int* getRand ...

  5. Spring之MVC模块

    Spring MVC的Controller用于处理用户的请求.Controller相当于Struts 1里的Action,他们的实现机制.运行原理都类似 Controller是个接口,一般直接继承Ab ...

  6. oracle伪列

    Oracle的伪列以及伪表 oracle系统为了实现完整的关系数据库功能,系统专门提供了一组成为伪列(Pseudocolumn)的数据库列,这些列不是在建立对象时由我们完成的,而是在我们建立时由Ora ...

  7. html5全解析

    htm是软件开发中非常基础的知识,也是很重要的知识,在web中是很重要的知识点,在此梳理一下主要内容: 1.HTML是什么? 全称为HyperText Markup Language,超文本标记语言, ...

  8. [ExtJS5学习笔记]第八节 Extjs5的Ext.toolbar.Toolbar工具条组件及其应用

    本文地址:http://blog.csdn.net/sushengmiyan/article/details/38515499 本文作者:sushengmiyan ------------------ ...

  9. shell 数据流重定向操作符总结

    最近看了鸟哥私房菜关于shell数据流重定向的内容,总结一下. 操作符: 1.标准输入(stdin):代码为0,符号:< 或者<< 2.标准输出(stdout):代码为1,符号:&g ...

  10. Cocos2D中Action的进阶使用技巧(二)

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 上回说到解决办法是使用CCTargetedAction类. C ...