Java自定义注解Annotation的使用
从 jdk5开始,Java增加了对元数据的支持,也就是Annotation,Annotation其实就是对代码的一种特殊标记,这些标记可以在编译,类加载和运行时被读取,并执行相应的处理。当然刚刚说了,Annotation只是一种标记,所以要是在代码里面不用这些标记也是能完成相应的工作的,只是有时候用注解能简化很多代码,看起来非常的简洁。 常见的注解(Annotation) @Override——限定重写父类方法 @Deprecated——标示已过时 @SuppressWarning——抑制编译器警告 JAVA的元注解 除了上面的注解,还有元注解。元注解是指注解的注解,包括@Retention @Target @Document @Inherited四种。 [email?protected] 这个是决定你Annotation存活的时间的,它包含一个RetationPolicy的value成员变量,用于指定它所修饰的Annotation保留时间,一般有: 1. Retationpolicy.CLASS:编译器将把注解记录在Class文件中, 不过当java程序执行的时候,JVM将抛弃它。不过当java程序执行的时候,JVM将抛弃它。 2. Retationpolicy.SOURCE : 默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得。 4. Retationpolicy.RUNTIME : 在Retationpolicy.CLASS的基础上,JVM执行的时候也不会抛弃它,所以我们一般在程序中可以通过反射来获得这个注解,然后进行处理。 首先要明确生命周期长度 SOURCE < CLASS < RUNTIME ,所以MT4下载教程前者能作用的地方后者一定也能作用。一般如果需要在运行时去动态获取注解信息,那只能用 RUNTIME 注解;如果要在编译时进行一些预处理操作,比如生成一些辅助代码(如 ButterKnife),就用 CLASS注解;如果只是做一些检查性的操作,比如 @Override 和 @SuppressWarnings,则可选用 SOURCE 注解。 [email?protected] 这个注解一般用来指定被修饰的注解修饰哪些元素,如下: ElementType.ANNOTATION_TYPE : //注解 ElementType.CONSTRUCTOR: //构造函数 ElementType.FIELD: //字段、枚举的常量 ElementType.LOCAL_VARIABLE: //局部变量 ElementType.METHOD: //方法 ElementType.PACKAGE: //包 ?? ElementType.PARAMETER://方法参数 ElementType.TYPE: //接口、类、枚举、注解 @Document 这个注解修饰的Annotation类可以被javadoc工具提取成文档 @Inherited 被他修饰的注解具有继承性,说明子类可以继承父类中的该注解 例子 自定义注解MyClassAnnotation @Retention(RetentionPolicy.RUNTIME) ? @Target(ElementType.TYPE) ? public @interface MyClassAnnotation { String value(); } 自定义注解MyFieldAnnotation @Retention(RetentionPolicy.RUNTIME) ? @Target(ElementType.FIELD) ? public @interface MyFieldAnnotation { public String name() default "fieldName"; } 自定义注解MyMethodAnnotation @Retention(RetentionPolicy.RUNTIME) ? @Target(ElementType.METHOD) ? public @interface MyMethodAnnotation { ??????String name(); ??????int age(); } 在实例中使用TestRuntimeAnnotation 来测试注解情况: @MyClassAnnotation(value = "test Class") public class TestRuntimeAnnotation { ????@MyFieldAnnotation ????public String fieldInfo = "FiledInfo"; ? @MyMethodAnnotation(age = 0,name = "zhangsan") ????public static String getMethodInfo() { ? ????????return TestRuntimeAnnotation.class.getSimpleName(); ? ????} ?? ????public static void main(String[]args) { ????????StringBuffer sb = new StringBuffer(); ? ????????Class<?> cls = TestRuntimeAnnotation.class; ? ????????sb.append("Class注解:").append("n"); ? ????????MyClassAnnotation myClassAnnotation = cls.getAnnotation(MyClassAnnotation.class); ? ????????if (myClassAnnotation != null) { ? ????????????sb.append(Modifier.toString(cls.getModifiers())).append(" ") ? ????????????????????.append(cls.getSimpleName()).append("n"); ? ????????????sb.append("注解值: ").append(myClassAnnotation.value()).append("nn"); ? ????????} ????????sb.append("Field注解:").append("n"); ? ????????Field[] fields = cls.getDeclaredFields(); ? ????????for (Field field : fields) { ? ???????? MyFieldAnnotation fieldInfo = field.getAnnotation(MyFieldAnnotation.class); ? ????????????if (fieldInfo != null) { ? ????????????????sb.append(Modifier.toString(field.getModifiers())).append(" ") ? ????????????????????????.append(field.getType().getSimpleName()).append(" ") ? ????????????????????????.append(field.getName()).append("n"); ? ????????????????sb.append("注解值: ").append(fieldInfo.name()).append("nn"); ? ????????????} ? ????????} ? ????? ????????sb.append("Method注解:").append("n"); ? ????????Method[] methods = cls.getDeclaredMethods(); ? ????????for (Method method : methods) { ? ???????? MyMethodAnnotation methodInfo = method.getAnnotation(MyMethodAnnotation.class); ? ????????????if (methodInfo != null) { ? ????????????????sb.append(Modifier.toString(method.getModifiers())).append(" ") ? ????????????????????????.append(method.getReturnType().getSimpleName()).append(" ") ? ????????????????????????.append(method.getName()).append("n"); ? ????????????????sb.append("注解值: ").append("n"); ? ????????????????sb.append("name: ").append(methodInfo.name()).append("n"); ? ????????????????sb.append("age: ").append(methodInfo.age()).append("n"); ? ????????????} ? ????????} ? ????????System.out.print(sb.toString()); ? ????} } 测试结果如下: Class注解: public TestRuntimeAnnotation 注解值: test Class Field注解: public String fieldInfo 注解值: fieldName Method注解: public static String getMethodInfo 注解值: name: zhangsan age: 0 定义注解 该注解可以验证成员属性是否为空,长度,提供了几种常见的正则匹配,也可以使用自定义的正则去判断属性是否合法,同时可以为该成员提供描述信息。 定义注解 该注解可以验证成员属性是否为空,长度,提供了几种常见的正则匹配,也可以使用自定义的正则去判断属性是否合法,同时可以为该成员提供描述信息。 package org.xdemo.validation.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.xdemo.validation.RegexType; /** ?* 数据验证 ?* @author Goofy ?*/ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD,ElementType.PARAMETER}) public @interface DV { ? ????//是否可以为空 ????boolean nullable() default false; ????//最大长度 ????int maxLength() default 0; ????//最小长度 ????int minLength() default 0; ????//提供几种常用的正则验证 ????RegexType regexType() default RegexType.NONE; ????//自定义正则验证 ????String regexExpression() default ""; ????//参数或者字段描述,这样能够显示友好的异常信息 ????String description() default ""; } 注解的解析 package org.xdemo.validation.annotation.support; import java.lang.reflect.Field; import org.xdemo.validation.RegexType; import org.xdemo.validation.annotation.DV; import org.xdemo.validation.utils.RegexUtils; import org.xdemo.validation.utils.StringUtils; /** ?* 注解解析 ?* @author Goofy ?*/ public class ValidateService { ????? ????private static DV dv; ????? ????public ValidateService() { ????????super(); ????} ????//解析的入口 ????public static void valid(Object object) throws Exception{ ????????//获取object的类型 ????????Class<? extends Object> clazz=object.getClass(); ????????//获取该类型声明的成员 ????????Field[] fields=clazz.getDeclaredFields(); ????????//遍历属性 ????????for(Field field:fields){ ????????????//对于private私有化的成员变量,通过setAccessible来修改器访问权限 ????????????field.setAccessible(true); ????????????validate(field,object); ????????????//重新设置会私有权限 ????????????field.setAccessible(false); ????????} ????} ? ????public static void validate(Field field,Object object) throws Exception{ ????????String description; ????????Object value; ????????//获取对象的成员的注解信息 ????????dv=field.getAnnotation(DV.class); ????????value=field.get(object); ????????if(dv==null)return; ????????description=dv.description().equals("")?field.getName():dv.description(); ????????/*************注解解析工作开始******************/ ????????if(!dv.nullable()){ ????????????if(value==null||StringUtils.isBlank(value.toString())){ ????????????????throw new Exception(description+"不能为空"); ????????????} ????????} ????????if(value.toString().length()>dv.maxLength()&&dv.maxLength()!=0){ ????????????throw new Exception(description+"长度不能超过"+dv.maxLength()); ????????} ????????? ????????if(value.toString().length()<dv.minLength()&&dv.minLength()!=0){ ????????????throw new Exception(description+"长度不能小于"+dv.minLength()); ????????} ????????if(dv.regexType()!=RegexType.NONE){ ????????????switch (dv.regexType()) { ????????????????case NONE: ????????????????????break; ????????????????case SPECIALCHAR: ????????????????????if(RegexUtils.hasSpecialChar(value.toString())){ ????????????????????????throw new Exception(description+"不能含有特殊字符"); ????????????????????} ????????????????????break; ????????????????case CHINESE: ????????????????????if(RegexUtils.isChinese2(value.toString())){ ????????????????????????throw new Exception(description+"不能含有中文字符"); ????????????????????} ????????????????????break; ????????????????case EMAIL: ????????????????????if(!RegexUtils.isEmail(value.toString())){ ????????????????????????throw new Exception(description+"地址格式不正确"); ????????????????????} ????????????????????break; ????????????????case IP: ????????????????????if(!RegexUtils.isIp(value.toString())){ ????????????????????????throw new Exception(description+"地址格式不正确"); ????????????????????} ????????????????????break; ????????????????case NUMBER: ????????????????????if(!RegexUtils.isNumber(value.toString())){ ????????????????????????throw new Exception(description+"不是数字"); ????????????????????} ????????????????????break; ????????????????case PHONENUMBER: ????????????????????if(!RegexUtils.isPhoneNumber(value.toString())){ ????????????????????????throw new Exception(description+"不是数字"); ????????????????????} ????????????????????break; ????????????????default: ????????????????????break; ????????????} ????????} ????????if(!dv.regexExpression().equals("")){ ????????????if(value.toString().matches(dv.regexExpression())){ ????????????????throw new Exception(description+"格式不正确"); ????????????} ????????} ????????/*************注解解析工作结束******************/ ????} } 用到的几个类 package org.xdemo.validation; /** ?* 常用的数据类型枚举 ?* @author Goofy ?* ?*/ public enum RegexType { ????? ????NONE, ????SPECIALCHAR, ????CHINESE, ????EMAIL, ????IP, ????NUMBER, ????PHONENUMBER; ?? } 其中正则验证类和字符串工具类请参考以下链接: SuperUtil之RegexUtils SuperUtil之StringUtils 使用方法 package org.xdemo.validation.test; import org.xdemo.validation.RegexType; import org.xdemo.validation.annotation.DV; public class User { ????@DV(description="用户名",minLength=6,maxLength=32,nullable=false) ????private String userName; ????? ????private String password; ????@DV(description="邮件地址",nullable=false,regexType=RegexType.EMAIL) ????private String email; public User(){} ????public User(String userName,String password,String email) { ????????super(); ????????this.userName = userName; ????????this.password = password; ????????this.email = email; ????} ????public String getUserName() { ????????return userName; ????} ????public void setUserName(String userName) { ????????this.userName = userName; ????} ????public String getPassword() { ????????return password; ????} ????public void setPassword(String password) { ????????this.password = password; ????} ????public String getEmail() { ????????return email; ????} ????public void setEmail(String email) { ????????this.email = email; ????} } 测试代码 import org.xdemo.validation.annotation.support.ValidateService; /** ?* @author Goofy ?*/ public class Test { ????public static void main(String[] args){ ????????User user=new User("张三","xdemo.org","[email?protected]"); ????????try { ????????????ValidateService.valid(user); ????????} catch (Exception e) { ????????????e.printStackTrace(); ????????} ????????user=new User("zhangsan","[email?protected]"); ????????try { ????????????ValidateService.valid(user); ????????} catch (Exception e) { ????????????e.printStackTrace(); ????????} ????????user=new User("zhangsan",""); ????????try { ????????????ValidateService.valid(user); ????????} catch (Exception e) { ????????????e.printStackTrace(); ????????} ????} } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |