Java Annotation-必须掌握的特性

简介: 什么是Annotation? Annotation翻译为中文即为注解,意思就是提供除了程序本身逻辑外的额外的数据信息。Annotation对于标注的代码没有直接的影响,它不可以直接与标注的代码产生交互,但其他组件可以使用这些信息。

什么是Annotation?

Annotation翻译为中文即为注解,意思就是提供除了程序本身逻辑外的额外的数据信息。Annotation对于标注的代码没有直接的影响,它不可以直接与标注的代码产生交互,但其他组件可以使用这些信息。

Annotation信息可以被编译进class文件,也可以保留在Java 虚拟机中,从而在运行时可以获取。甚至对于Annotation本身也可以加Annotation。

那些对象可以加Annotation

类,方法,变量,参数,包都可以加Annotation。

内置的Annotation

@Override 重载父类中方法 @Deprecated 被标注的方法或类型已不再推荐使用

@SuppressWarnings 阻止编译时的警告信息。其需要接收一个String的数组作为参数。 可供使用的参数有:

  • unchecked
  • path
  • serial
  • finally
  • fallthrough

可以用与其他annotation上的annotation

  • @Retention

确定Annotation被保存的生命周期, 需要接收一个Enum对象RetentionPolicy作为参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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
}
  • @Documented 文档化

  • @Target

表示该Annotation可以修饰的范围,接收一个Enum对象EnumType的数组作为参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public enum ElementType {
    /** Class, interface (including annotation type), or enum declaration */
    TYPE,

    /** Field declaration (includes enum constants) */
    FIELD,

    /** Method declaration */
    METHOD,

    /** Parameter declaration */
    PARAMETER,

    /** Constructor declaration */
    CONSTRUCTOR,

    /** Local variable declaration */
    LOCAL_VARIABLE,

    /** Annotation type declaration */
    ANNOTATION_TYPE,

    /** Package declaration */
    PACKAGE
}
  • @Inherited

该Annotation可以影响到被标注的类的子类。

自定义Annotation

JSE5.0以后我们可以自定义Annotation。下面就是一个简单的例子。

1
2
3
4
5
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MethodAnnotation {

}

下面的Person对象使用了自定义的MethodAnnotation。

1
2
3
4
5
6
7
8
9
10
11
12
public class Person {

    public void eat() {
        System.out.println("eating");
    }

    @MethodAnnotation
    public void walk() {
        System.out.print("walking");
    }

}

我们可以通过反射获取Annotation的信息。

1
2
3
4
5
6
7
        Class<Person> personClass = Person.class;
        Method[] methods = personClass.getMethods();
        for(Method method : methods){
            if (method.isAnnotationPresent(MethodAnnotation.class)){
                method.invoke(personClass.newInstance());
            }
        }

输出:

1
walking

我们也可以给自定义的Annotation加方法。

1
2
3
4
5
@Target(ElementType.TYPE)
public @interface personAnnotation {
    int id() default 1;
    String name() default "bowen";
}

下面是对personAnnotation的使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
@personAnnotation(id = 8, name = "john")
public class Person {

    public void eat() {
        System.out.println("eating");
    }

    @MethodAnnotation
    public void walk() {
        System.out.print("walking");
    }

}

Annotation是如何被处理的

当Java源代码被编译时,编译器的一个插件annotation处理器则会处理这些annotation。处理器可以产生报告信息,或者创建附加的Java源文件或资源。如果annotation本身被加上了RententionPolicy的运行时类,则Java编译器则会将annotation的元数据存储到class文件中。然后,Java虚拟机或其他的程序可以查找这些元数据并做相应的处理。

当然除了annotation处理器可以处理annotation外,我们也可以使用反射自己来处理annotation。Java SE 5有一个名为AnnotatedElement的接口,Java的反射对象类Class,Constructor,Field,Method以及Package都实现了这个接口。这个接口用来表示当前运行在Java虚拟机中的被加上了annotation的程序元素。通过这个接口可以使用反射读取annotation。AnnotatedElement接口可以访问被加上RUNTIME标记的annotation,相应的方法有getAnnotation,getAnnotations,isAnnotationPresent。由于Annotation类型被编译和存储在二进制文件中就像class一样,所以可以像查询普通的Java对象一样查询这些方法返回的Annotation。

Annotation的广泛使用

Annotation被广泛用于各种框架和库中,下面就列举一些典型的应用.

Junit

Junit是非常著名的一款单元测试框架,使用Junit的时候需要接触大量的annotation。

  • @Runwith 自定义测试类的Runner

  • @ContextConfiguration 设置Spring的ApplicationContext

  • @DirtiesContext 当执行下一个测试前重新加载ApplicationContext.

  • @Before 调用测试方法前初始化

  • @After 调用测试方法后处理

  • @Test 表明该方法是测试方法

  • @Ignore 可以加在测试类或测试方法上,忽略运行。

  • @BeforeClass:在该测试类中的所有测试方法执行前调用,只被调用一次(被标注的方法必须是static)

  • @AfterClass:在该测试类中的所有的测试方法执行完后调用,只被执行一次(被标注的方法必须是static)

Spring

Spring 号称配置地狱,Annotation也不少。

  • @Service 给service类加注解

  • @Repository 给DAO类加注解

  • @Component 给组件类加注解

  • @Autowired 让Spring自动装配bean

  • @Transactional 配置事物

  • @Scope 配置对象存活范围

  • @Controller 给控制器类加注解

  • @RequestMapping url路径映射

  • @PathVariable 将方法参数映射到路径

  • @RequestParam 将请求参数绑定到方法变量

  • @ModelAttribute 与model绑定

  • @SessionAttributes 设置到session属性

Hibernate

  • @Entity 修饰entity bean

  • @Table 将entity类与数据库中的table映射起来

  • @Column 映射列

  • @Id 映射id

  • @GeneratedValue 该字段是自增长的

  • @Version 版本控制或并发性控制

  • @OrderBy 排序规则

  • @Lob 大对象标注

Hibernate还有大量的关于联合的annotation和继承的annotation,这里就不意义列举了。

JSR 303 - Bean Validation

JSR 303 - Bean Validation是一个数据验证的规范,其对Java bean的验证主要通过Java annotation来实现。

  • @Null被注释的元素必须为 null

  • @NotNull被注释的元素必须不为 null

  • @AssertTrue被注释的元素必须为 true@AssertFalse被注释的元素必须为 false@Min(value)被注释的元素必须是一个数字,其值必须大于等于指定的最小值

  • @Max(value)被注释的元素必须是一个数字,其值必须小于等于指定的最大值

  • @DecimalMin(value)被注释的元素必须是一个数字,其值必须大于等于指定的最小值

  • @DecimalMax(value)被注释的元素必须是一个数字,其值必须小于等于指定的最大值

  • @Size(max, min)被注释的元素的大小必须在指定的范围内

  • @Digits (integer, fraction)被注释的元素必须是一个数字,其值必须在可接受的范围内

  • @Past被注释的元素必须是一个过去的日期

  • @Future被注释的元素必须是一个将来的日期

  • @Pattern(value)被注释的元素必须符合指定的正则表达式

其实还有很多使用了annotaion的framework或library,这里就不一一列举了,希望大家能举一反三,深入了解Java中的annotation。

相关文章
|
11天前
|
安全 Java 数据安全/隐私保护
|
11天前
|
搜索推荐 Java
Java的面向对象特性主要包括封装、继承和多态
【4月更文挑战第5天】Java的面向对象特性主要包括封装、继承和多态
13 3
|
1月前
|
人工智能 Java 编译器
Java 19的未来:新特性、性能优化和更多
Java 19的未来:新特性、性能优化和更多
|
1月前
|
Java API 数据处理
Java 8新特性之Stream API详解
【2月更文挑战第22天】本文将深入探讨Java 8中引入的Stream API,这是一种基于函数式编程的新特性,用于处理集合数据。我们将详细介绍Stream的基本概念、操作方法以及在实际开发中的应用,帮助读者更好地理解和使用这一强大的工具。
|
1月前
|
Java API
Java 8新特性之Lambda表达式与Stream API
【2月更文挑战第21天】本文将介绍Java 8中的两个重要特性:Lambda表达式和Stream API。Lambda表达式是Java 8中引入的一种新的编程语法,它允许我们将函数作为参数传递给方法,从而使代码更加简洁、易读。Stream API是一种用于处理集合的新API,它提供了一种高效且易于使用的处理数据的方式。本文将通过实例讲解这两个特性的基本用法以及它们如何帮助我们编写更简洁、高效的Java代码。
|
7天前
|
Java API 开发者
Java 8新特性之函数式编程实战
【4月更文挑战第9天】本文将深入探讨Java 8的新特性之一——函数式编程,通过实例演示如何运用Lambda表达式、Stream API等技术,提高代码的简洁性和执行效率。
|
8天前
|
存储 Java API
java8新特性 lambda表达式、Stream、Optional
java8新特性 lambda表达式、Stream、Optional
|
24天前
|
分布式计算 Java 程序员
Java 8新特性之Lambda表达式与Stream API
本文将详细介绍Java 8中的两个重要新特性:Lambda表达式和Stream API。Lambda表达式是Java 8中引入的一种简洁、匿名的函数表示方法,它允许我们将函数作为参数传递给其他方法。而Stream API则是一种新的数据处理方式,它允许我们以声明式的方式处理数据,从而提高代码的可读性和可维护性。通过本文的学习,你将能够掌握Lambda表达式和Stream API的基本用法,以及如何在项目中应用这两个新特性。
28 10
|
29天前
|
Java API 数据处理
Java 8新特性之Lambda表达式和Stream API
【2月更文挑战第27天】本文将介绍Java 8中的两个重要特性:Lambda表达式和Stream API。Lambda表达式是一种新的编程语法,它允许我们将函数作为参数传递给方法,从而使代码更加简洁。Stream API是一种处理数据的新方法,它可以让我们以声明式方式处理数据,提高代码的可读性和可维护性。
|
1月前
|
Java
【java8新特性篇】常用函数式接口
【java8新特性篇】常用函数式接口
16 0
【java8新特性篇】常用函数式接口