Annotation注解

2020-06-23  本文已影响0人  码而优则仕

Annotation注解

上节介绍的反射似乎很厉害,可以在运行时操作和修改对象的行为,但是要使用反射,最起码要知道待反射的类所在的包路径和类名。所以项目中我们必须记录哪些类是需要反射进行获取的。

标记类信息的方式有如下几种:

  1. XML方式保存类相关信息:

    <bean id="welcomeService" class="cn.com.yuns.service.impl.WelcomeServiceImpl"/>
    
  2. 用注解来保存类相关信息

    @Service
    public class JybWechatService implements IJybWechatService {
    

注解

提供一种为程序元素设置元数据的方法,什么是所谓的元数据?就是数据的数据即对数据的一种描述

总的来说:注解就是将我们需要的数据存储起来,在以后的某一时刻去使用,可能是编译时也可能是运行时。

所有注解均继承自Annotation这个接口。

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface TestAnnotation {
}

但是我们看注解里面没有体现继承自Annotation这个接口,怎样才能看到呢?

首先需要执行 javac com/yuns/demo/annotation/TestAnnotation.java 命令将.java文件编译为.class文件,然后使用命令

javap -verbose com/yuns/demo/annotation/TestAnnotation 命令将.class文件反编译出来,我们可以看见反编译出来的类信息中就有接口继承自Annotation的信息:

Classfile /Users/wsq/Documents/demo/simpleframework/src/main/java/com/yuns/demo/annotation/TestAnnotation.class
  Last modified 2020-6-23; size 405 bytes
  MD5 checksum b830500c3cccd0ce2cbaaba7c81d3196
  Compiled from "TestAnnotation.java"
public interface com.yuns.demo.annotation.TestAnnotation extends java.lang.annotation.Annotation
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
Constant pool:
   #1 = Class              #14            // com/yuns/demo/annotation/TestAnnotation
   #2 = Class              #15            // java/lang/Object
   #3 = Class              #16            // java/lang/annotation/Annotation
   #4 = Utf8               SourceFile
   #5 = Utf8               TestAnnotation.java
   #6 = Utf8               RuntimeVisibleAnnotations
   #7 = Utf8               Ljava/lang/annotation/Target;
   #8 = Utf8               value
   #9 = Utf8               Ljava/lang/annotation/ElementType;
  #10 = Utf8               METHOD
  #11 = Utf8               Ljava/lang/annotation/Retention;
  #12 = Utf8               Ljava/lang/annotation/RetentionPolicy;
  #13 = Utf8               SOURCE
  #14 = Utf8               com/yuns/demo/annotation/TestAnnotation
  #15 = Utf8               java/lang/Object
  #16 = Utf8               java/lang/annotation/Annotation
{
}
SourceFile: "TestAnnotation.java"
RuntimeVisibleAnnotations:
  0: #7(#8=[e#9.#10])
  1: #11(#8=e#12.#13)

注解的功能:

简单来说注解只是一种特殊的注释,如果没有解析它的代码,它可能连注释都不如。

注解的分类

  1. 标准注解:Override(重写),Deprecated(表示不再维护,有风险,不鼓励使用),SuppressWarnings(表示需要忽略某项Warning)
  2. 元注解(注解的注解):@Retention,@Target,@Inherited,@Documented
  3. 自定义注解:根据业务需要定义的注解(定义和元注解息息相关,自定义注解是使用元注解来定义的)

元注解

用于修饰注解的注解,通常用在注解的定义上;

Java中的元注解

  1. @Target :指定注解的作用,目标

    被描述的注解可以被用在什么地方:

    packages,types(类,接口,枚举,Annotation类型)

    类型成员(方法,构造方法,成员变量,枚举值)

    方法参数和本地变量(循环变量,catch参数)

    public enum ElementType {
        /**类级别 Class, interface (including annotation type), or enum declaration */
        TYPE,
    
        /** 成员变量Field declaration (includes enum constants) */
        FIELD,
    
        /** 方法级别 Method declaration */
        METHOD,
    
        /** 方法参数 Formal parameter declaration */
        PARAMETER,
    
        /** 构造器 Constructor declaration */
        CONSTRUCTOR,
    
        /** 本地变量 Local variable declaration */
        LOCAL_VARIABLE,
    
        /** 注解标签 Annotation type declaration */
        ANNOTATION_TYPE,
    
        /** 包 Package declaration */
        PACKAGE,
    
        /**
         * Type parameter declaration
         *
         * 标注类型参数,作用在泛型类的实参 @since 1.8
         */
        TYPE_PARAMETER,
    
        /**
         * Use of a type 可以使用在所有地方
         *
         * @since 1.8
         */
        TYPE_USE
    }
    

    TYPE:

    @Target({ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Component
    public @interface Controller {
    

    FIELD

    @Target({ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface Autowired {
    

    METHOD

    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @RequestMapping(method = RequestMethod.DELETE)
    public @interface DeleteMapping {
    

PARAMETER

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestBody {
  1. @Retention:指定注解的生命周期

    没描述的注解在什么范围内有效

public enum RetentionPolicy {
    /**
     * Annotations are to be discarded by the compiler.
     * 被描述的注解在原文件中保留,但是在编译后的class文件中去除
     */
    SOURCE,

    /**
     * Annotations are to be recorded in the class file by the compiler
     * but need not be retained by the VM at run time.  This is the default
     * behavior.不仅出现在原文件中,页也出现在class文件中
     */
    CLASS,

    /**
     * Annotations are to be recorded in the class file by the compiler and
     * retained by the VM at run time, so they may be read reflectively.
     * 该类在运行时获得该注解的信息,运行时保留注解信息
     * @see java.lang.reflect.AnnotatedElement
     */
    RUNTIME
}

SOURCE

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface TestAnnotation {
}
public class HpMouse implements Mouse {
    @Override
    @TestAnnotation
    public void sayHi() {
        System.out.println("我是惠普鼠标");
    }
}
javac com/yuns/demo/pattern/factory/entity/HpMouse.java  编译后:
package com.yuns.demo.pattern.factory.entity;

public class HpMouse implements Mouse {
    public HpMouse() {
    }
    public void sayHi() {
        System.out.println("我是惠普鼠标");
    }
}

CLASS

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.CLASS)
public @interface TestAnnotation {
}
public class HpMouse implements Mouse {
    @Override
    @TestAnnotation
    public void sayHi() {
        System.out.println("我是惠普鼠标");
    }
}

javac com/yuns/demo/pattern/factory/entity/HpMouse.java 编译后:

public class HpMouse implements Mouse {
    public HpMouse() {
    }
    @TestAnnotation
    public void sayHi() {
        System.out.println("我是惠普鼠标");
    }
}

RUNTIME

该类在运行时获得该注解的信息,运行时保留注解信息,程序可以在运行时通过反射来获取注解的信息

@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
  1. @Documented:指定直接是否应当被包含在JavaDoc文档中

    加这个注解的注解会在生成的JavaDoc文档中出现注解

  2. @Inherited:是否允许子类继承该注解

    具有可继承性,注解修饰某个类,则该类的自类可以继承这个注解

上一篇下一篇

猜你喜欢

热点阅读