前言
为什么突然想起来注解呢?今天上午同事遇到一个和注解相关的问题,JSP页面传值到后台后(其实前后端并不分离),但是在POJO类上的校验注解值不满足的条件下也通过了,让我给帮忙看看。因为其他组的同事相同的通用代码并没有这个问题,而且对注解的处理是封装在框架中的,所以一开始便排除了问题在后台思路,转向页面传值去调查。虽然最后找到原因是因为没有清空Eclipse的.class文件重新编译,但是感觉已经对之前学过的注解部分的知识生疏了。刚好今天没加班,就赶紧复习一下。
本想在网上找两篇文章回忆一下,但是好像例子写得都不完整。刚好前段时间刚买了一本《Java编程思想》,就赶紧翻开看了一下,一直记得书里给出的例子也是数据库字段注解相关的。
相关概念及原理
参见 ==> 《Java编程思想》第二十章<注解>。
四个元注解:
- @Target
- @Retention
- @Document
- @Inherited
注解主要是用户按自己的需求来实现。
一个简单的例子
先创建两个注解,@Digits 和 @NotEmpty,用来注解属性是否满足给定条件。
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| package com.Annotation;
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface Digits { public int maxLength();
public int fraction() default 0; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| package com.Annotation;
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface NotEmpty { }
|
定义一个处理类处理自定义注解:(主要利用反射机制)
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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| package com.Annotation;
import java.lang.annotation.Annotation; import java.lang.reflect.Field;
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)
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 26 27 28 29 30 31 32 33 34 35 36 37 38
| package com.Annotation;
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); } }
|