简单说说注解到底用在哪了?
本文只简单分析注解的使用,供注解初学者尝试使用,使用过程中还需要自己加强原理追溯;
包含(注解是什么,如何自定义注解,注解作用在那里,如何在开发中使用注解)
1、注解是什么?
官方定义:
注解(Annotation),也叫元数据。一种代码级别的说明。
what ???? 啥是元数据??
元数据:描述数据的数据。(举例:我形容某个人,哪身高,体重,肤色,头发等 就是元数据了)
但是,注解是描述什么的呢?(类, 方法, 属性..)
常规理解:注解就是对指定对象的额外信息指定和约束,但这个指定和约束必须要有监督者,才真正发挥作用。
比如:
@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;
}
真正有意义就是这一段利用反射,获取属性值,比较注解约束内容。而这个方法的逻辑就是赤裸裸的监督者! 监督被约束的对象是否按照约定进行。
所以: 注解是鱼 , 反射解析是水, 两者相辅相成。
好的! 那么咱们进入一个全流程(自定义注解)
1、定义注解(也就是建立法律约束)
2、在将要被约束的对象/方法/属性 上添加注解(法律针对对象)
3、特定的反射功能,获取注解,解析注解并校验 (法律解读,监督者检查是否违背法律)
4、在特定的地方调用反射功能 也就是调用监督者。
开发过程什么情况下使用注解?
1、有校验需求时
2、有约束需求时
3、有隔离了原本业务的非业务功能时 ...
等等,这个感觉有点像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); } }

浙公网安备 33010602011771号