自定义注解
一、 目的:
自定义注解实现,POJO校验
二、元注解、标准注解
@Target 定义范围
CONSTRUCTOR |
用于描述构造器(领盒饭)。 |
FIELD |
用于描述域(领盒饭)。 |
LOCAL_VARIABLE |
用于描述局部变量(领盒饭)。 |
METHOD |
用于描述方法。 |
PACKAGE |
用于描述包(领盒饭)。 |
PARAMETER |
用于描述参数。 |
TYPE |
用于描述类或接口(甚至 enum )。 |
@Retention 运行时效
取值 |
描述 |
SOURCE |
在源文件中有效(即源文件保留,领盒饭)。 |
CLASS |
在 class 文件中有效(即 class 保留,领盒饭)。 |
RUNTIME |
在运行时有效(即运行时保留)。 |
@Documented 在默认的情况下javadoc命令不会将我们的annotation生成再doc中去的,所以使用该标记就是告诉 jdk让它也将annotation生成到doc中去
@Inherited 子类继承注解
自动定义注解,例如
public @interface Complexity { public enum Level { VERY_SIMEPLE, SIMPLE, MEDIUM, COMPLEX, VERY_COMPLEX } default @Complexity.MEDIUM }
@Target(ElementType.FIELD) //作用域 @Retention(RetentionPolicy.RUNTIME) //运行时效 @Documented @Inherited //继承注解 public @interface IsEmptyAnnotation { public boolean isEmpty() default true; public String message() default "字段不能为空"; }
三、注解处理器
处理器的代码虽然写完了,但是这还没完呢,剩下还有非常重要的步骤,那就是添加注册信息。因为注解处理器是属于javac的一个平台级的功能,所以我们的使用方式是将代码打包成jar的形式,这样就可以在其他第三方项目当中使用了。而在打包jar之前,则要在项目中添加注册信息
四、实现POJO的校验
User
public class User { @IsEmptyAnnotation public String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }
@IsEmptyAnnotation
@Target(ElementType.FIELD) //作用域 @Retention(RetentionPolicy.RUNTIME) //运行时效 @Documented @Inherited //继承注解 public @interface IsEmptyAnnotation { public boolean isEmpty() default true; public String message() default "字段不能为空"; }
AnnotationDealUtil 利用反射的机制对注解进行校验
public class AnnotationDealUtil { private static Logger log = Logger.getAnonymousLogger(); @SuppressWarnings("unchecked") public static Map<String, Object> validate(Object bean) { Map<String, Object> result = new HashMap<String, Object>(); result.put("message", "验证通过"); result.put("result", true); Class<?> cls = bean.getClass(); // 检测field是否存在 try { // 获取实体字段集合 Field[] fields = cls.getDeclaredFields(); for (Field f : fields) { // 通过反射获取该属性对应的值 f.setAccessible(true); // 获取字段值 Object value = f.get(bean); // 获取字段上的注解集合 Annotation[] arrayAno = f.getAnnotations(); for (Annotation annotation : arrayAno) { // 获取注解类型(注解类的Class) Class<?> clazz = annotation.annotationType(); // 获取注解类中的方法集合 Method[] methodArray = clazz.getDeclaredMethods(); for (Method method : methodArray) { // 获取方法名 String methodName = method.getName(); // 过滤错误提示方法的调用 if(methodName.equals("message")) { continue; } // 初始化注解验证的方法处理类 (我的处理方法卸载本类中) Object obj = AnnotationDealUtil.class.newInstance(); // 获取方法 try { // 根据方法名获取该方法 Method m = obj.getClass().getDeclaredMethod(methodName, Object.class, Field.class); // 调用该方法 result = (Map<String, Object>)m.invoke(obj, value, f); /* 验证结果 有一处失败则退出 */ if(result.get("result").equals(false)) { return result; } } catch (Exception e) { e.printStackTrace(); log.info("找不到该方法:"+methodName); } } } } } catch (Exception e) { e.printStackTrace(); log.info("验证出错"); } return result; } public Map<String, Object> isEmpty(Object value, Field field) { Map<String, Object> validateResult = new HashMap<String, Object>(); IsEmptyAnnotation annotation = field.getAnnotation(IsEmptyAnnotation.class); if(value == null || value.equals("")) { validateResult.put("message", field.getName() + annotation.message()); validateResult.put("result", false); } else { validateResult.put("message", "验证通过"); validateResult.put("result", true); } return validateResult; } }
main
public static void main(String[] args) { User advertise = new User(); advertise.setName("a"); System.out.println(AnnotationDealUtil.validate(advertise)); }
参考链接:
粗略的讲解了,AOP,注解,自定义注解,拦截器 的基本知识 http://www.cnblogs.com/shipengzhi/articles/2716004.html
注解实现的校验,一般都是由反射实现 http://blog.csdn.net/bao19901210/article/details/17201173/