博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
(原创)JAVA注解应用——实现属性的自动检测
阅读量:6502 次
发布时间:2019-06-24

本文共 12953 字,大约阅读时间需要 43 分钟。

一、什么是注解

Annotation(注解)是JDK5.0及以后版本引入的新特性。它可以用于创建文档,跟踪代码中的依赖性,甚至执行基本编译时检查。注解是以‘@注解名’在代码中存在的,根据注解参数的个数,我们可以将注解分为:标记注解、单值注解、完整注解三类。它们都不会直接影响到程序的语义,只是作为注解(标识)存在,我们可以通过反射机制编程实现对这些元数据(用来描述数据的数据)的访问。

二、注解能做什么

Annotation提供了一种安全的类似注释的机制,为我们在代码中添加信息提供了一种形式化得方法,使我们可以在稍后某个时刻方便的使用这些数据(通过解析注解来使用这些数据),用来将任何的信息或者元数据与程序元素(类、方法、成员变量等)进行关联。其实就是更加直观更加明了的说明,这些说明信息与程序业务逻辑没有关系,并且是供指定的工具或框架使用的。Annotation像一种修饰符一样,应用于包、类型、构造方法、方法、成员变量、参数及本地变量的申明语句中。

Annotation其实是一种接口。通过java的反射机制相关的API来访问Annotation信息。相关类(框架或工具中的类)根据这些信息来决定如何使用该程序元素或改变它们的行为。Java语言解释器在工作时会忽略这些Annotation,因此在JVM中这些Annotation是“不起作用”的,只能通过配套的工具才能对这些Annotation类型的信息进行访问和处理。

三、使用注解实现JAVABEAN中属性的自动检测

我们要接下来实现的功能很简单,假设有这么一个场景:外部需要调用某系统接口实现某一功能,其中接口参数是用JavaBean进行传递,JavaBean中定义了几个属性,系统中对这几个属性有着严格的限制,比如:非空、长度限制、参数取值限制等等。

按照传统的方法,我们可能需要针对每个javabean中的每个属性都要写对应的逻辑的判断,设想一下,如果这个系统的接口有1000个,是不是我们应该事先1000个逻辑?NONONO,不需要,java注解功能可以很好的事先这个问题。

1.要实现上面的三个监测,我们需要定义三个不同的注解,代码如下:

1 package com.maomq.testannotation.annotation; 2  3 import java.lang.annotation.Documented; 4 import java.lang.annotation.ElementType; 5 import java.lang.annotation.Retention; 6 import java.lang.annotation.RetentionPolicy; 7 import java.lang.annotation.Target; 8  9 /**10  * 必填项注解11  * @author maomq12  * @since 2013-08-2913  */14 @Retention(RetentionPolicy.RUNTIME)15 @Target({ElementType.FIELD})16 @Documented17 public @interface Required {18 19 }
非空注解
1 package com.maomq.testannotation.annotation; 2  3 import java.lang.annotation.Documented; 4 import java.lang.annotation.ElementType; 5 import java.lang.annotation.Retention; 6 import java.lang.annotation.RetentionPolicy; 7 import java.lang.annotation.Target; 8  9 /**10  * 元素长度范围注解11  * @author maomq12  * @since 2013-08-2913  */14 @Retention(RetentionPolicy.RUNTIME)15 @Target({ElementType.FIELD})16 @Documented17 public @interface LengthLimitRange {18 19     static final int MIN_VALUE = 0;20     21     static final int MAX_VALUE = 255;22     23     public int minValue() default MIN_VALUE;24     25     public int maxValue() default MAX_VALUE;    26 }
长度限制注解
1 package com.maomq.testannotation.annotation; 2  3 import java.lang.annotation.Documented; 4 import java.lang.annotation.ElementType; 5 import java.lang.annotation.Retention; 6 import java.lang.annotation.RetentionPolicy; 7 import java.lang.annotation.Target; 8  9 /**10  * 字符串范围注解11  * @author maomq12  * @since 2013-08-2913  */14 @Retention(RetentionPolicy.RUNTIME)15 @Target({ElementType.FIELD})16 @Documented17 public @interface ArrayStringRange {18     public String[] valueArray();19 }
字符串取值范围注解

2.注解定义好了,下一步应该定义注解的判断逻辑,这里我们引入一个接口,它将定义所有的监测规则

1 package com.maomq.testannotation.checker; 2  3 import java.lang.reflect.Field; 4  5 /** 6  * 注解检测实现接口类 7  *  8  * @author maomq 9  * @since 2013-08-2910  */11 public interface FieldAnnotationChecker {12 13     /**14      * 返回check结果15      * 16      * @param value17      * @param field18      * @return boolean19      */20     public boolean check(Object value, Field field);21 }
1 package com.maomq.testannotation.checker; 2  3 import java.lang.reflect.Field; 4 import java.util.Collection; 5 import java.util.Map; 6  7 /** 8  * 注解检测实现类 9  * @author maomq10  * @since 2013-08-2911  */12 public class RequiredAnnotationChecker implements FieldAnnotationChecker {13 14     @Override15     public boolean check(Object value, Field field) {16         if (null == value)17         {18             System.out.println("The required value is null!");19             return false;20         }21         22         if (value instanceof String)23         {24             String strValue = (String) value;25             if(strValue.isEmpty())26             {27                 System.out.println("The required value is null!");28                 return false;29             }30         }31         else if (value instanceof Collection
)32 {33 Collection
collValue = (Collection
) value;34 if(collValue.isEmpty())35 {36 System.out.println("The required value is null!");37 return false;38 }39 }40 else if (value instanceof Map
)41 {42 Map
mapValue = ( Map
) value;43 if(mapValue.isEmpty())44 {45 System.out.println("The required value is null!");46 return false;47 }48 }49 return true;50 }51 52 }
必填项监测实现类
1 package com.maomq.testannotation.checker; 2  3 import java.lang.reflect.Field; 4 import java.util.Collection; 5 import java.util.Map; 6  7 import com.maomq.testannotation.annotation.LengthLimitRange; 8  9 /**10  * 注解检测实现类11  * 12  * @author maomq13  * @since 2013-08-2914  */15 public class LengthLimitRangeAnnotationChecker implements16         FieldAnnotationChecker {17 18     @Override19     public boolean check(Object value, Field field) {20         if (null == value) {21             System.out.println("The value is null or empty!");22             return true;23         }24 25         LengthLimitRange lengthRange = field26                 .getAnnotation(LengthLimitRange.class);27 28         int maxValue = lengthRange.maxValue();29 30         int minValue = lengthRange.minValue();31 32         if (value instanceof String) {33             String strValue = (String) value;34             if (strValue.length() > maxValue || strValue.length() < minValue) {35                 System.out36                         .println("The input value is out of the value limit range!");37                 return false;38             }39         } else if (value instanceof Collection
) {40 Collection
collValue = (Collection
) value;41 if (collValue.size() > maxValue || collValue.size() < minValue) {42 System.out43 .println("The input value is out of the value limit range!");44 return false;45 }46 } else if (value instanceof Map
) {47 Map
mapValue = (Map
) value;48 if (mapValue.values().size() > maxValue49 || mapValue.values().size() < minValue) {50 System.out51 .println("The input value is out of the value limit range!");52 return false;53 }54 }55 return true;56 }57 58 }
长度限制检测实现类
1 package com.maomq.testannotation.checker; 2  3 import java.lang.reflect.Field; 4  5 import com.maomq.testannotation.annotation.ArrayStringRange; 6  7 /** 8  * 注解检测实现类 9  * 10  * @author maomq11  * @since 2013-08-2912  */13 public class ArrayStringRangeAnnotationChecker implements14         FieldAnnotationChecker {15 16     @Override17     public boolean check(Object value, Field field) {18         if (null == value) {19             System.out.println("The value is null or empty!");20             return true;21         }22 23         ArrayStringRange arrayRange = field24                 .getAnnotation(ArrayStringRange.class);25 26         String[] strArray = arrayRange.valueArray();27 28         if (value instanceof String && strArray.length > 0) {29             for (String strTemp : strArray) {30                 if (strTemp.equalsIgnoreCase(value.toString())) {31                     return true;32                 }33             }34             System.out.println("The input value is out of the value range!");35             return false;36         }37 38         return true;39     }40 41 }
字符串取值范围实现类

3.检测逻辑也完成了,我们是针对每个JAVABEAN中的属性,因此,不可避免的需要一个Util类获取JavaBean中的属性,上代码:

1 package com.maomq.testannotation;  2   3 import java.lang.annotation.Annotation;  4 import java.lang.reflect.Field;  5 import java.util.ArrayList;  6 import java.util.HashMap;  7 import java.util.List;  8 import java.util.Map;  9  10 import com.maomq.testannotation.annotation.ArrayStringRange; 11 import com.maomq.testannotation.annotation.LengthLimitRange; 12 import com.maomq.testannotation.annotation.Required; 13 import com.maomq.testannotation.checker.ArrayStringRangeAnnotationChecker; 14 import com.maomq.testannotation.checker.FieldAnnotationChecker; 15 import com.maomq.testannotation.checker.LengthLimitRangeAnnotationChecker; 16 import com.maomq.testannotation.checker.RequiredAnnotationChecker; 17  18 /** 19  * 注解检测测试类 20  * @author maomq 21  * @since 2013-08-29 22  */ 23 public class AnnotationCheckerUtil { 24  25     private static Map
, FieldAnnotationChecker> holder = new HashMap
, FieldAnnotationChecker>(); 26 27 static { 28 holder.put(Required.class, new RequiredAnnotationChecker()); 29 holder.put(LengthLimitRange.class, new LengthLimitRangeAnnotationChecker()); 30 holder.put(ArrayStringRange.class, new ArrayStringRangeAnnotationChecker()); 31 } 32 33 /** 34 * 获取Bean中所有的属性 35 * @param clazz 36 * @param fieldList 37 */ 38 private static void getAllField(Class
clazz, List
fieldList) 39 { 40 if (fieldList == null) 41 { 42 fieldList = new ArrayList
(); 43 } 44 45 Field[] fieldArray = clazz.getDeclaredFields(); 46 for (Field fieldTemp : fieldArray) 47 { 48 fieldList.add(fieldTemp); 49 } 50 51 Class
superClazz = clazz.getSuperclass(); 52 53 if(superClazz != Object.class) 54 { 55 getAllField(superClazz, fieldList); 56 } 57 } 58 59 /** 60 * 对传入的JAVABean属性进行检测(使用注解) 61 * @param objParam 62 * @return 63 */ 64 public static boolean checkField(Object objParam) 65 { 66 List
fieldList = new ArrayList
(); 67 68 getAllField(objParam.getClass(), fieldList); 69 70 if (fieldList == null || fieldList.isEmpty()) 71 { 72 return true; 73 } 74 75 for (Field fieldTemp : fieldList) 76 { 77 fieldTemp.setAccessible(true); 78 Object value = null; 79 try { 80 value = fieldTemp.get(objParam); 81 } catch (IllegalArgumentException e) { 82 e.printStackTrace(); 83 } catch (IllegalAccessException e) { 84 e.printStackTrace(); 85 } 86 87 Annotation[] fieldAnnotations = fieldTemp.getAnnotations(); 88 89 for(Annotation annotation : fieldAnnotations) 90 { 91 FieldAnnotationChecker checker = holder.get(annotation.annotationType()); 92 93 if (null != checker && !checker.check(value, fieldTemp)) 94 { 95 return false; 96 } 97 } 98 } 99 100 return true;101 }102 }

4.上面的工作都已经准备好了,现在可以测试一下了,首先定义一个javabean,并对其中需要检测的项目予以标注。

1 package com.maomq.testannotation; 2  3 import com.maomq.testannotation.annotation.ArrayStringRange; 4 import com.maomq.testannotation.annotation.LengthLimitRange; 5 import com.maomq.testannotation.annotation.Required; 6  7 /** 8  * 注解检测测试Bean类 9  * @author maomq10  * @since 2013-08-2911  */12 public class TestAnnotationBean {13     //必填项检测14     @Required15     private String userId;16     //必填,长度限制17     @Required18     @LengthLimitRange(minValue = 1, maxValue = 10)19     private String userName;20     //必填,取值范围限制21     @Required22     @ArrayStringRange(valueArray = {"football", "basketball", "swimming"})23     private String habby;24     25     @SuppressWarnings(value = { "" })26     private String description;27 28     public String getUserId() {29         return userId;30     }31 32     public void setUserId(String userId) {33         this.userId = userId;34     }35 36     public String getUserName() {37         return userName;38     }39 40     public void setUserName(String userName) {41         this.userName = userName;42     }43 44     public String getHabby() {45         return habby;46     }47 48     public void setHabby(String habby) {49         this.habby = habby;50     }51 52     public String getDescription() {53         return description;54     }55 56     public void setDescription(String description) {57         this.description = description;58     }59 }

对上面的结果进行验证:

1 package com.maomq.testannotation; 2  3 /** 4  * 注解检测测试类 5  * @author maomq 6  * @since 2013-08-29 7  */ 8 public class TestAnnotation { 9 10 11     public static void main(String[] args) {12         TestAnnotationBean testAnnotationBean =new TestAnnotationBean();13         14         testAnnotationBean.setUserId("AAA");15         testAnnotationBean.setUserName("12345678901");16         testAnnotationBean.setHabby("walking");17         testAnnotationBean.setDescription("ggsgsgsggs");18         19         if(!AnnotationCheckerUtil.checkField(testAnnotationBean))20         {21             System.out.println("Something is wrong!");22         }23     }24 25 }

输出如我们所料:habby不符合取值范围。

The input value is out of the value limit range!Something is wrong!

四、小结

通过上面的例子我们可以大致了解注解的功能,如果需要深挖,建议大家学习一下Spring中对java注解功能应用,尤其是涉及事务控制的注解,真的很精髓,有兴趣的同学一定要抽时间学习一下,我这只是抛砖引玉,还望不吝赐教。

转载于:https://www.cnblogs.com/MarvinMao/p/3308514.html

你可能感兴趣的文章
Java基础学习总结(1)——equals方法
查看>>
Maven学习总结(6)——Maven与Eclipse整合
查看>>
HTML5:理解head
查看>>
oracle
查看>>
java SpringUtil获取bean
查看>>
Centos6.4最小化安装系统初始化脚本
查看>>
PaaS变厚了
查看>>
赛门铁克开启“容灾即服务”时代
查看>>
复杂度归纳--小结
查看>>
基础篇9-python基本数据结构-列表
查看>>
PHP学习笔记 第八讲 Mysql.简介和创建新的数据库
查看>>
【git】git入门之把自己的项目上传到github
查看>>
js获取鼠标位置
查看>>
2016.8.11 DataTable合并及排除重复方法
查看>>
php 魔术方法 说明
查看>>
Mysql
查看>>
POJ-1860-Currency Exchange
查看>>
跨越企业的“中等收入陷阱”
查看>>
Android 开发者必知的开发资源
查看>>
软件工程技术基础-(软件复用技术)
查看>>