Java注解简单例子

了解Java注解(@Annotation)

前言

为什么突然想起来注解呢?今天上午同事遇到一个和注解相关的问题,JSP页面传值到后台后(其实前后端并不分离),但是在POJO类上的校验注解值不满足的条件下也通过了,让我给帮忙看看。因为其他组的同事相同的通用代码并没有这个问题,而且对注解的处理是封装在框架中的,所以一开始便排除了问题在后台思路,转向页面传值去调查。虽然最后找到原因是因为没有清空Eclipse的.class文件重新编译,但是感觉已经对之前学过的注解部分的知识生疏了。刚好今天没加班,就赶紧复习一下。

本想在网上找两篇文章回忆一下,但是好像例子写得都不完整。刚好前段时间刚买了一本《Java编程思想》,就赶紧翻开看了一下,一直记得书里给出的例子也是数据库字段注解相关的。

相关概念及原理

参见 ==> 《Java编程思想》第二十章<注解>。

四个元注解:

  • @Target
  • @Retention
  • @Document
  • Inherited

注解主要是用户按自己的需求来实现。

一个简单的例子

先创建两个注解,@Digits和@NotEmpty,用来注解属性是否满足给定条件。

代码如下:

package com.Annotation;

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

/**
 * <p>
 * 标注一个字段只能为数字,且最大长度为maxLength,最大小数位为fraction
 * 默认没有小数位
 * </p>
 *
 * @author [email protected]
 * @since 2019-05-14 21:42
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Digits {
    public int maxLength();

    public int fraction() default 0;
}
package com.Annotation;

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

/**
 * <p>
 * 标注一个字段不能为空
 * </p>
 *
 * @author [email protected]
 * @since 2019-05-14 21:47
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface NotEmpty {
}

定义一个处理类处理自定义注解:(主要利用反射机制)

package com.Annotation;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;

/**
 * <p>
 * 处理自定义注解
 * </p>
 *
 * @author [email protected]
 * @since 2019-05-14 21:59
 */
public class AnnotationProcesser {
    public void process(Table table) throws ClassNotFoundException, IllegalAccessException, NoSuchFieldException {
        Class clazz = table.getClass();
        if (clazz == null) {
            throw new ClassNotFoundException("class not found!");
        }
        Field[] fields = clazz.getDeclaredFields();
        String fieldName;
        for (Field field : fields) {
            System.out.println("--------------------------");
            field.setAccessible(true);
            Annotation[] annotations = field.getDeclaredAnnotations();
            fieldName = field.getName();
            System.out.println("--> info: into " + fieldName);
            for (Annotation annotation : annotations) {
                System.out.println("--> info: " + annotation.annotationType());
                if (annotation instanceof Digits) {
                    System.out.println("--> info: get @Digits annotation on " + fieldName);
                    int maxLength = ((Digits) annotation).maxLength();
                    int annotatedFraction = ((Digits) annotation).fraction();
                    String[] fraction = String.valueOf(table.getCount()).split("\\.");
                    if (String.valueOf(table.getCount()).length() > maxLength) {
                        System.out.println("--> error: maxLength exceed!");
                    }
                    if (fraction.length > 1 && fraction[1].length() > annotatedFraction) {
                        System.out.println("--> error:fraction length exceed!");
                    } else {
                        System.out.println("--> info: " + fieldName + " validate success!");
                    }
                } else if (annotation instanceof NotEmpty) {
                    System.out.println("--> info: get @NotEmpty annotation on " + fieldName);
                    if (table.getDescription() == null || "".equals(table.getDescription())) {
                        System.out.println("--> error: empty is not allowed!");
                    } else {
                        System.out.println("--> info: " + fieldName + " validate success!");
                    }
                }
            }
        }
    }
}

主测试类:(省略getter和setter

package com.Annotation;

/**
 * <p>
 * 自定义注解测试类
 * </p>
 *
 * @author [email protected]
 * @since 2019-05-14 21:49
 */
public class Table {
    @Digits(maxLength = 6, fraction = 2)
    private double count;

    @NotEmpty
    private String description;

    public Table(double count, String description) {
        this.count = count;
        this.description = description;
    }

    public static void main(String[] args) throws IllegalAccessException, ClassNotFoundException, NoSuchFieldException {
        Table testTable1 = new Table(1234567, "description1");
        Table testTable2 = new Table(12.001, "description2");
        Table testTable3 = new Table(123.01, "description3");
        Table testTable4 = new Table(123.01, null);
        Table testTable5 = new Table(123.01, "description5");

        AnnotationProcesser processer = new AnnotationProcesser();
        processer.process(testTable1);
        processer.process(testTable2);
        processer.process(testTable3);
        processer.process(testTable4);
        processer.process(testTable5);
    }
}