VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > 编程开发 > Java教程 >
  • Java注解

Java注解,顾名思义,就是用于标注和解释Java代码的。

在各种Java框架中,我们只需要使用少量的注解即可实现一些强大的功能。在这些看似强大的功能背后,其实现原理却并不复杂。

 

1. 什么是注解

让我们看看最常见的注解@Override。在我们使用IDE复写接口代码时,这个注解会自动生成出来,被标注在被复写的方法上,用于代表这个方法被重写了。

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

可见注解定义的关键字为:@interface

 

在注解@Override上,还有两个注解:@Target@Retention

这里可以看到注解后面有值的存在,让我们再看看@Target的定义:

复制代码
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
    /**
     * Returns an array of the kinds of elements an annotation type
     * can be applied to.
     * @return an array of the kinds of elements an annotation type
     * can be applied to
     */
    ElementType[] value();
}
复制代码

注解内的定义上,与@Override不同的是,内部较之多了一个方法:ElementType[] value();从返回值上可以看到使用了ElementType类型,而注解使用时也使用了该类型。

该定义的实际描述为:value可以接收一个ElementType[]作为描述。对于@Target(ElementType.METHOD),其完整写法应该为:

@Target(value = {ElementType.METHOD})

value即定义的描述(方法)名称,其值为ElementType组成的数组。

但是注解的特性中,接收的数组中只含有一个元素时,只需要直接使用该值。即

@Target(value = ElementType.METHOD)

另外,当只使用了一个描述,且该描述名为value时,可以省略描述名。最终简化为了:

@Target(ElementType.METHOD)

 

说完注解的用法后,再来看看这两个注解的用途,在定义一个注解时,这两个注解经常会使用到。

@Target:

用于描述注解可标记的位置,描述值来自ElementType内的枚举值。

复制代码
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

可以标注到类上,即定义为class、interface、enum的类上。

例如@Target、Spring中的@Component

FIELD

可以标注到属性声明上。

例如Spring中的@Autowired

METHOD

可以标注到方法(函数)声明上。

例如@Override、Spring中的@Autowired

PARAMETER

可以标注到方法的参数上。

例如mybatis的@Param,Spring的@RequestBody

因此@Target用于描述标注在什么位置。

 

@Retention

用于描述何时有效。描述值来自RetentionPolicy 枚举值。

复制代码
public enum RetentionPolicy {
    /**
     * Annotations are to be discarded by the compiler.
     */
    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,

    /**
     * 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:源代码中有效、CLASS:编译后class文件内有效,RUNTIME:以及运行时VM有效。

这个值也与通过注解实现自动装配等功能提供了基础。

 

通常来说,仅作为描述使用的注解,例如@Override,仅在源代码有效即可,因为仅用于编码人员观看,在运行期不需要用到。

对于Spring中品种繁多的各类注解,其标注的使用范围均为:RetentionPolicy.RUNTIME。

 

2. 如何获取注解中描述的值

获取描述的值非常简单,我们先自己定义一个注解@ForClass,并为他定义两个描述值:

复制代码
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ForClass {
    
    String value() default "";
    
    String[] packages() default {};
}
复制代码

default代表使用默认值,这样描述值就是非必填项,获取时也会取到默认值,default的存在令许多Spring中的描述值不必填写。

我们再定义一个类,在类上使用该注解描述这个类:

@ForClass("UseAnnotationClass")
public class UseAnnotationClass {

}

最后,在main函数中开始获取UserAnnotationClass的描述值:

复制代码
public static void main(String[] args) {
    // 获取标注在UseAnnotationClass类上的注解
    ForClass forClass = UseAnnotationClass.class.getAnnotation(ForClass.class);
    // 获取其中value的值
    String value = forClass.value();
}
复制代码

如此只需做简单的几步操作便可获取到value的描述值。packages亦是同理。

 

如今再来谈谈Spring中的注解,以@Component为例。

在Spring中,我们通常要给Spring提供项目路径,并将Spring组件置于子包中。

在main类上使用@SpringBootApplication其实就能获取到项目的父路径。因此SpringBoot中通常不需要告诉Spring。

有了这个路径后,递归扫描子包,查看哪些类上包含@Component注解,由此获取到所有的使用到@Component注解的类。

获取到这些类后,Spring便知道我们想把这个类放入IOC容器中,于是将其放入IOC容器中。

 

对注解的使用不过是Spring的冰山一角,以后的文章中会从jdk本身的功能上,逐渐向大家解开Spring的各色看似神奇的操作。

 

原文:https://www.cnblogs.com/mrjanon/p/java-annotation.html

 


相关教程