一. 元注解

自定义注解首先需要了解四个元注解,它是注解在注解上的注解,用于定义自定义注解的特性。

  1. @Retention
    用于表示注解在什么情况下生效。
    RetentionPolicy.SOURCE(编译器不会将注解编译到class中)
    RetentionPolicy.CLASS(会编译到class但不会被加载到jvm)
    RetentionPolicy.Runtime(在jvm中生效)
  2. @Documented
    注解,是被用来指定自定义注解是否能随着被定义的java文件生成到JavaDoc文档当中。
  3. @Target
    作用的位置,是作用于class还是field等。
    取值为 ElementType枚举类。
  4. @Inherited
    该注解作用的class或field等可以被子类继承。
    值得一提,定义注解是 public @interface Demozhujie{} 的方式来定义的,@interface不能够implements和extends。

下面是一个demo,演示如何定义一个注解。

import java.lang.annotation.*;
@Inherited
@Documented
@Target({ElementType.Field})
@Retention(RetentionPolicy.RUNTIME)

public @interface Translate {
    /**
     @interface定义字段的方式与一般的class不同,需要()。
    */
    String value();

    boolean enable() default true;
}

二. 如何处理注解

了解定义注解,使用注解其实不用多说,放在想要加的位置即可。
那么我们又该如何使用注解呢?常用的方式是通过spring aop或其他aop方式在某个位置拦截进行注解的逻辑处理,我们的重点不是aop,所以下面只是一个拦截到注解时的代码逻辑。

示例:@Translate注解表示的字段全部翻译为英文,当然这里的英文。
// 1. 通过反射获取到注解,clz是当前class
 Class clz = ...
 Translate annotation = (Translate) clz.getAnnotation(Translate.class);
 
 // 2. 判断当前class哪个字段被加了注释
 Arrays.stream(  clz.getFields() )
                .forEach( field -> {
                    if(field.isAnnotationPresent(Translational.class) && field.getAnnotation(Translational.class).enable()){
                        markFields.add(field.getAnnotation(Translational.class).value());
                    }
                });
  
  //3. 根据第二步找到的字段,通过反射调用getter方法获取到属性值
  // element为当前正处理的对象
  // getIdMethodName需要驼峰,这里就不做字母的大小写转换了
  String getIdMethodName = "get"+markFields.get(0);
  Object fieldValue = MethodUtils.invokeMethod(element,getIdMethodName);
  
  //4. 将上一步获取到的属性值与字典数据对比,通过反射调用setter方法替换属性值
  String translateValue = getValueByDICT(fieldValue);
  MethodUtils.invokeMethod(element,setIdMethodName,translateValue);