简单说说注解到底用在哪了?

本文只简单分析注解的使用,供注解初学者尝试使用,使用过程当中还须要本身增强原理追溯;java

包含(注解是什么,如何自定义注解,注解做用在那里,如何在开发中使用注解)api

 

一、注解是什么?测试

  官方定义:spa

  注解(Annotation),也叫元数据。一种代码级别的说明。
what ???? 啥是元数据??代理

  元数据:描述数据的数据。(举例:我形容某我的,哪身高,体重,肤色,头发等 就是元数据了)对象

  可是,注解是描述什么的呢?(类, 方法, 属性..)blog

  常规理解注解就是对指定对象的额外信息指定和约束,但这个指定和约束必须要有监督者,才真正发挥做用。 开发

  好比:get

  
@Target({ElementType.FIELD, ElementType.METHOD})  // 做用对象(FIELD:属性,METHOD:方法 固然还有其余枚举,)
@Retention(RetentionPolicy.RUNTIME) //(运行时生效)
public @interface FieldCanNotNull {
}

 

上面就是一个简单入门的注解,在运行的时候,是有效的,可被获取及解析的。
//测试类
public class Person{

@FieldCanNotNull  //这个注解就是咸鱼
private String merchangNO;

}

 

可是,这个在没有代码解释的时候,毫无心义。

怎么才能让它变得有意义,有价值?
 
那就是经过某种方式 ,能够在运行的时候获取到这个对象的
merchangNO 属性信息,而且获取这个属性的元数据。而 @FieldCanNotNull 就是元数据。
想要获取的话,那就须要经过反射的方式,或者当前类的基础信息,并获取当前属性的注解信息。

    /**
     * 属性非空校验
     * @param object
     * @return
     */
    public static boolean isNull4fields(Object object){
        if (isNull(object)){
            throw NetInException.PARAM_REQUIRED_ERROR.newInstance("object  can not be null");
        }
        List<Field> fields = getAllFields(object.getClass(), new ArrayList<>()); //获取全部属性
        if (CollectionUtils.isEmpty(fields)){
            return false;
        }

        Iterator<Field> iterator = fields.iterator(); //获取迭代器

        Object fieldVal;
        while ( iterator.hasNext()) {
            Field field = iterator.next();
            if ( field.isAnnotationPresent(FieldCanNotNull.class)){ //判断当前属性是否有 FieldCanNotNull 注解
                fieldVal = invokeGetMethod(field.getName(), "", object); //调用当前属性的get 方法获取属性值
                if(isNull(fieldVal)){ //若是当前属性址是空
                    String errMsg = field.getName() + "  can not be null"; //组装信息 抛出异常
                    throw NetInException.PARAM_REQUIRED_ERROR.newInstance(errMsg, null);
                }
            }else{
                continue;
            }

        }
        return false;
    }

   真正有意义就是这一段利用反射,获取属性值,比较注解约束内容。而这个方法的逻辑就是赤裸裸的监督者! 监督被约束的对象是否按照约定进行it

因此: 注解是鱼 , 反射解析是水, 二者相辅相成。



好的! 那么我们进入一个全流程(自定义注解)


一、定义注解(也就是创建法律约束)
二、在将要被约束的对象/方法/属性 上添加注解(法律针对对象)
三、特定的反射功能,获取注解,解析注解并校验 (法律解读,监督者检查是否违背法律)
四、在特定的地方调用反射功能 也就是调用监督者。

开发过程什么状况下使用注解?
  一、有校验需求时
  二、有约束需求时
  三、有隔离了本来业务的非业务功能时 ...

等等,这个感受有点像AOP的思想啊,没错,咱们在使用的过程通常还真的是把这个监督者使用AOP思想来实现。这样就从核心业务上把注解给解析判断喽!
那怎么样呢?还有啥?
既然是AOP那么代理是必然要有的。
  因此最终经常使用的就是 , 在代理类中 使用反射 前置处理 解析注解 最后调用目标方法;

例以下面:使用Spring实现AOP 在调用方法以前,进行前置注解解析和处理

前置处理(AOP)
@Aspect
public class VerifyAop {

    /**
     * 校验参数
     * @param joinPoint
     * @throws Throwable
     */
    public void verifyMethod(JoinPoint joinPoint) throws Throwable {

        Object[] args = joinPoint.getArgs();
        for (Object arg:args){
            VerifyUtil.isNull4fields(arg);
        }
    }

    /**
     * 环绕处理
     * @param point
     * @return
     * @throws Throwable
     */
    public Object exeMethod(ProceedingJoinPoint point) throws Throwable {
        return point.proceed();
    }

}

 

校验方法(监督者)
public class VerifyUtil {
    private VerifyUtil(){};

    /**
     * 校验参数为否为空
     * @param param
     * @param paramDesc 参数名
     */
    public static void validateNotEmptyParam(Object param, String paramDesc){
        if (param == null){
            throw  NetInException.PARAM_REQUIRED_ERROR.newInstance(paramDesc + "为必填项");
        }

        if ((param instanceof Map && MapUtils.isEmpty((Map)param))
                || (param.getClass().isArray() && ArrayUtils.getLength(param) ==0)
                || (param instanceof CollectionUtils && CollectionUtils.isEmpty((Collection)param))
                || (param instanceof String && StringUtils.isEmpty(((String)param).trim()))){

            throw  NetInException.PARAM_VALIDATE_ERROR.newInstance(paramDesc + "不能为空");
        }
    }

    /**
     * 判断对象是否为空
     * @param object
     * @return
     */
    public static boolean isNull(Object object){
        if (object==null){
            return true;
        }else if (StringUtils.isEmpty(object.toString())){
            return true;
        }
        return false;
    }
/**
     * 属性非空校验
     * @param object
     * @return
     */
    public static boolean isNull4fields(Object object){
        if (isNull(object)){
            throw NetInException.PARAM_REQUIRED_ERROR.newInstance("object  can not be null");
        }
        List<Field> fields = getAllFields(object.getClass(), new ArrayList<>()); //获取全部属性
        if (CollectionUtils.isEmpty(fields)){
            return false;
        }

        Iterator<Field> iterator = fields.iterator(); //获取迭代器

        Object fieldVal;
        while ( iterator.hasNext()) {
            Field field = iterator.next();
            if ( field.isAnnotationPresent(FieldCanNotNull.class)){ //判断当前属性是否有 FieldCanNotNull 注解
                fieldVal = invokeGetMethod(field.getName(), "", object); //调用当前属性的get 方法获取属性值
                if(isNull(fieldVal)){ //若是当前属性址是空
                    String errMsg = field.getName() + "  can not be null"; //组装信息 抛出异常
                    throw NetInException.PARAM_REQUIRED_ERROR.newInstance(errMsg, null);
                }
            }else{
                continue;
            }

        }
        return false;
    }
/** *获取当前类及当前类的多层父类属性集合 * @param clazz * @param fields * @return */ public static List<Field> getAllFields(Class clazz,List<Field> fields ){ Field[] declaredFields = clazz.getDeclaredFields(); Class superclass = clazz.getSuperclass(); if (superclass == null || "Object".equals(superclass.getSimpleName())){ fields.addAll(Lists.newArrayList(declaredFields)); return fields; }else { List<Field> fieldsList = Arrays.asList(declaredFields); fields.addAll(fieldsList); getAllFields(superclass, fields); } return fields; } /** * 调用指定对象的getXX 方法(用于获取某个对象的某个属性的值) * @param fieldName * @param suffix * @param object * @return */ private static Object invokeGetMethod(String fieldName, String suffix, Object object ) { Method mget = ReflectionUtils.findMethod(object.getClass(), "get" + StringUtils.capitalize(fieldName) + StringUtils.trimToEmpty(suffix)); return ReflectionUtils.invokeMethod(mget, object); } }
相关文章
相关标签/搜索