[01] 注解的基本认识和元注解


1、什么是注解

用一个词就可以描述注解,那就是元数据,即一种描述数据的数据。所以,可以说注解就是源代码的元数据。

@Override 
public String toString() {
    return "This is String Representation of current object.";
}
如上代码,重写了toString()方法并使用了@Override注解。但是,即使不使用@Override注解标记代码,程序也能够正常执行。那么,该注解表示什么?有什么好处?

事实上,@Override告诉编译器这个方法是一个重写方法(描述方法的元数据),如果父类中不存在该方法,编译器便会报错,提示该方法没有重写父类中的方法。如果我不小心拼写错误,例如将toString()写成了toStrring(),而且我也没有使用@Override注解,那程序依然能编译运行,但运行结果会和我期望的大不相同。


2、注解的意义

在进行Java程序开发的时候,免不了和各种配置文件打交道,以经典的框架Spring或者Hibernate来说,不论是IOC的bean配置,还是持久化的ORM映射关系配置,都有各自的xml格式的配置文件。

这些配置文件都必须与Java代码同步,否则的话就会出现问题。然而把同一份信息保存在两个地方,并不是一个好的主意,因为维护随着代码量会越来越繁琐,理想的情况下把配置信息和代码都在同一个地方维护就好了。

JDK5中引入了注解机制,它类似于代码中的注释,不同的是注解不是提供代码功能的说明,而是实现程序功能的重要组成部分。在Spring或者Hibernate等主流框架中我们已经可以看到,已经开始可以使用注解的方式来替代xml配置文件,达到简化程序配置的目的。


3、元注解

元注解的作用就是负责注解其他注解

Java5.0定义了4个标准的meta-annotation类型,它们被用来提供对其他annotation类型作说明:
  • @Target  注解用于什么地方
  • @Retention  注解类型的存活时间
  • @Documented  注解是否包含在JavaDoc中
  • @Inherited  是否允许子类继承该注解

3.1 @Target

@Target 说明了Annotation所修饰的范围,表示该注解用于什么地方,如果不明确指出,该注解可以放在任何地方:
  • packages
  • types(类、接口、枚举、Annotation类型)
  • 类型成员(方法、构造方法、成员变量、枚举值)
  • 方法参数和本地变量(如循环变量、catch参数)

以下是一些可用的参数
  • ElementType.TYPE (描述类、接口、注解、或者枚举)
  • ElementType.FIELD (描述实例变量)
  • ElementType.METHOD (描述方法)
  • ElementType.PARAMETER (描述参数)
  • ElementType.CONSTRUCTOR (描述构造方法)
  • ElementType.LOCAL_VARIABLE (描述局部变量)
  • ElementType.ANNOTATION_TYPE (描述另一个注解)
  • ElementType.PACKAGE (描述包)

示例:
(1)注解Table可以用于注解类、接口(包括注解类型) 或enum声明
(2)注解NoDBColumn仅可用于注解类的成员变量
@Target(ElementType.TYPE)
public @interface Table {
    /**
     * 数据表名称注解,默认值为类名称
     * @return
     */
    public String tableName() default "className";
}

@Target(ElementType.FIELD)
public @interface NoDBColumn {

}

3.2 @Retention

某些Annotation仅出现在源代码中,而被编译器丢弃;而另一些却被编译在class文件中;编译在class文件中的Annotation可能会被虚拟机忽略,而另一些在class被装载时将被读取(请注意并不影响class的执行,因为Annotation与class在使用上是被分离的)。

使用这个meta-Annotation可以对Annotation的“生命周期”限制,即@Retention定义了该Annotation被保留的时间长短

以下是一些可用的参数:
  • RetentionPoicy.SOURCE (源文件中有效,即源文件保留)
  • RetentionPoicy.CLASS (class文件中有效,即class保留)
  • RetentionPoicy.RUNTIME (运行时有效,即运行时保留)

示例:
(1)Column注解的的RetentionPolicy的属性值是RUNTIME,这样注解处理器可以通过反射,获取到该注解的属性值,从而去做一些运行时的逻辑处理
(2)@Column是个修饰属性的,在运行时有效的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
    public String name() default "fieldName";
    public String setFuncName() default "setField";
    public String getFuncName() default "getField"; 
    public boolean defaultDBValue() default false;
}

3.3 @Documented

该注解用于描述其它类型的annotation应该被作为被标注的程序成员的公共API,因此可以被例如javadoc此类的工具文档化。Documented是一个标记注解,没有成员

3.4 @Inherited

该注解是一个标记注解,阐述了某个被标注的类型是被继承的。如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类。


4、参考链接


 

posted @ 2017-09-01 11:52  Dulk  阅读(963)  评论(0编辑  收藏  举报