注解全解析

  • 什么是注解?

  • 注解有什么作用?

  • 注解是怎么干活的?

  • 如何自定义注解?

什么是注解

  • 注解即元数据,一种描述数据的数据,可以说注解就是源代码的元数据

  • Annotation是一种应用于类、方法、参数、变量、构造器及包声明中的特殊修饰符

  • Annotation不能影响程序代码的运行,无论增加、删除注解,代码都始终如一的执行

  • 元数据(metadata),数据的数据

    • 元数据可以用来创建文档,跟踪代码的依赖性,执行编译时格式检查,代替已有的配置文件

    • 元数据以标签的形式存在于Java代码中,描述的信息是类型安全的(内部字段有明确类型)

  • Annotation类型定义了Annotation的名字、类型成员默认值,一个Annotation类型可以是一个特殊的java接口

注解有什么作用

  • 使用XML描述元数据:XML是为了分离代码和配置而引入,但有时候我们希望使用一些和代码紧耦合的描述

  • Annotation出现之前,开发人员使用自己的方式定义元数据,如标记interfaces,注释,transient等

  • Annotation给了一个统一的标准规范,在许多框架中与XML结合使用,平衡两者的利弊

注解是怎么干活的

  • 看源码@Override注解,你可能会疑惑,它什么都没有做,那它是如何检查在父类中有一个同名的函数

  • 强调:Annotation仅仅是元数据,和业务逻辑无关

  • Annotation并不直接对程序的语法产生作用,但是会提供一些程序之外的数据或者信息,影响工具或者类库对程序的处理或者调用的方式,从而影响程序运行时的行为

元注解

  • 元注解的作用就是负责注解其他注解,meta-annotation类型

  • @Target:用于描述注解的使用范围,即被描述的注解可以用在什么地方

    • ElementType.TYPE:用于描述类、接口或enum声明

    • ElementType.FIELD:用于描述实例变量,包括enum常量

    • ElementType.METHOD:用于描述方法

    • ElementType.PARAMETER:用于描述参数

    • ElementType.CONSTRUCTOR:用于描述构造器

    • ElementType.LOCAL_VARIABLE:用于描述局部变量

    • ElementType.ANNOTATION_TYPE:用于描述注解类型,另一个注释

    • ElementType.PACKAGE:用于记录Java文件的package信息

    • ElementType.TYPE_PARAMETER:可以用在Type的声明前

    • ElementType.TYPE_USE:可以用在所有使用Type的地方

      • 初始化对象:String myString = new @NotNull String();

      • 使用 throws 表达式:public void validateValues() throws @Critical ValidationFailedException{ }

  • @Retention:表示需要在什么级别保存该注释信息,用于描述注解的生命周期,即被描述的注解在什么范围内有效

    • RetentionPolicy.SOURCE:在编译阶段丢弃,编译之后就不再有任何意义,如@Override@SuppressWarnings

    • RetentionPolicy.CLASS:在类加载的时候丢弃,在字节码文件的处理中使用,注解默认使用这种方式

    • RetentionPolicy.RUNTIME:不会丢弃,运行时也保留该注解,可以使用反射机制读取该注解信息,自定义注解通常使用这种方式

  • @Documented:注解是否包含在JavaDoc中

  • @Inherited:是一个标记注解,如果使用了该注解修饰的annotation注解的class,会被作用于该class的子类

如何自定义注解

  • 自定义注解:@Todo

package com.adagio.demo;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 自定义注解
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Todo {
    
    public enum Priority{LOW, MEDIUM, HIGH}
    
    public enum Status{STARTED, NOT, NOT_STARTED}
    
    String author() default "Yash";
    
    Priority priority() default Priority.LOW;
    
    Status status() default Status.NOT_STARTED;

}
  • 如果注解只有一个属性,可以直接命名为"value",使用时无需在标明属性名

package com.adagio.demo;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Author {
    
    String value();
    
}
  • 注解元素必须有确定的值,可以在定义注解的默认值中指定,也可以在使用注解时指定

  • 使用反射读取注解信息:BusinessLogic

package com.adagio.demo;

import java.lang.reflect.Method;

public class BusinessLogic {
    
    @Todo(priority = Todo.Priority.MEDIUM, author = "Yashwant", status = Todo.Status.STARTED)
    public void incompleteMethod(){
        
    }
    
    @Author("Yashwant")
    public void someMethod(){
        
    }

    public void readAnnotationInfo(){
        Class<BusinessLogic> businessLogicClass = BusinessLogic.class;
        for(Method method : businessLogicClass.getMethods()){
            Todo todoAnnotation = method.getAnnotation(Todo.class);
            if(todoAnnotation != null){
                System.out.println("Method Name:" + method.getName());
                System.out.println("Author:" + todoAnnotation.author());
                System.out.println("Priority:" + todoAnnotation.priority());
                System.out.println("Status:" + todoAnnotation.author());
            }
        }
    }
    
    public static void main(String[] args) {
        System.out.println("开始读取》》》》");
        BusinessLogic b = new BusinessLogic();
        b.readAnnotationInfo();
        System.out.println("读取结束》》》》");
    }
}

注解用例

  • 注解的功能很强大,Spring和Hibernate这些框架在日志和有效性中大量使用了注解功能

  • 注解可以应用在使用标记接口的地方,不同的是标记的接口用来定义完整的类,但你可以为单个方法定义注解,如将一个方法暴露为服务

  • servlet3.0引入的新注解,和servlet安全相关的注解:

    • HandlesTypes 该注解用来表示一组传递给ServletContainerInitializer的应用类

    • HttpConstraint 该注解代表所有HTTP方法的应用请求的安全约束

    • HttpMethodConstraint 指明不同类型请求的安全约束

    • MultipartConfig 该注解标注在Serblet上,表处理请求MIME类型是multipart/form-data

    • ServletSecurity 该注解标注在Servlet继承类上,强制该HTTP协议请求遵循安全约束

    • WebFilter 该注解用来声明一个Servlet过滤器

    • WebInitParam 该注解用来声明Servlet或是过滤器中的初始化参数,通常配合@WebServlet或 @WebFilter使用

    • WebListener 该注解为Web应用程序上下文中不同类型的事件声明监听器

    • WebServlet 该注解用来声明一个Servlet的配置

参考文档:
http://www.importnew.com/1029...
http://www.cnblogs.com/peida/...
http://www.cnblogs.com/peida/...
https://www.ibm.com/developer...


麦冬
315 声望13 粉丝

越成熟的稻穗,越饱满厚实