问题场景,需要写一个功能,对100多张表进行操作,因为代码是低代码开发平台生成的,所以有一定的规律性,因为可以通过Controler进行字符串操作获取到操作的表名。但是,备不住有某些同事要展示个性修改Controler名字或者表名,所以我又添加了一个自定义注解,用来表示本Controler操作的是哪个数据表。
1,创建注解类
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author mazheng
* @title: MyAnnotation
* @description: 自定义注解类
* @date 2021/11/11 11:04
*/
public class MyAnnotation {
/**
* @param
* @return
* @throws
* @author mazheng
* @date 2021/11/11 11:05
* @Description 获取表名
*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ImportTableName {
String tableName();
}
}
对于上面的代码,我们关注点主要是:
@Target :
表示注解生效的位置,主要参数有
/** Class, interface (including annotation type), or enum declaration
类、接口(包括注解类型) 或enum声明上生效*/
TYPE,
/** Field declaration (includes enum constants) 域生命 */
FIELD,
/** Method declaration 方法上生效*/
METHOD,
/** Formal parameter declaration 用于描述参数*/
PARAMETER,
/** Constructor declaration 构造方法*/
CONSTRUCTOR,
/** Local variable declaration 局部变量描述*/
LOCAL_VARIABLE,
/** Annotation type declaration 注释类型声明*/
ANNOTATION_TYPE,
/** Package declaration 用在包上*/
PACKAGE,
/**
* Type parameter declaration 参数类型声明
*
* @since 1.8
*/
TYPE_PARAMETER,
/**
* Use of a type
*
* @since 1.8
*/
TYPE_USE
这里我使用 METHOD 和 TYPE,表示方法或者类上加这个注解都行。
@Retention
表明注解存在多久
/**
* Indicates how long annotations with the annotated type are to
* be retained. If no Retention annotation is present on
* an annotation type declaration, the retention policy defaults to
* {@code RetentionPolicy.CLASS}.
*
* <p>A Retention meta-annotation has effect only if the
* meta-annotated type is used directly for annotation. It has no
* effect if the meta-annotated type is used as a member type in
* another annotation type.
*
* @author Joshua Bloch
* @since 1.5
* @jls 9.6.3.2 @Retention
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
/**
* Returns the retention policy.
* @return the retention policy
*/
RetentionPolicy value();
}
主要策略如下
public enum RetentionPolicy {
/**
* Annotations are to be discarded by the compiler.
* 注解将被编译器丢弃
*/
SOURCE,
/**
* Annotations are to be recorded in the class file by the compiler
* but need not be retained by the VM at run time. This is the default
* behavior.
* 注释将由编译器记录在类文件中,但在运行时不需要由 VM 保留。这是默认行为
*/
CLASS,
/**
* Annotations are to be recorded in the class file by the compiler and
* retained by the VM at run time, so they may be read reflectively.
*
* @see java.lang.reflect.AnnotatedElement
* 注解会被编译器记录在类文件中,并在运行时由 VM 保留,因此它们可以被反射读取。
*/
RUNTIME
}
我用的也是RUNTIME 这个参数
@interface
表明这是一个注解类型,里面的tablename是我自定义的变量
到这里自定义接口的注解类部分已经完成了,剩下就是使用和获取他
2,使用自定义注解
@Api(tags="测试Controler")
@RestController
@RequestMapping("/test")
// 下面这个就是我们的自定义注解
@MyAnnotation.ImportTableName(tableName = "testTableName")
@Slf4j
public class testController {
//... 具体的方法
}
3,判断是否使用了自定义注解,以及自定义注解所带的值
// 下面一行是为了获取类名,因为我用的SPring AOP获取的,所以有Signature接口
Class clazz = signature.getDeclaringType();
// 获取表名 @Todo 可能会有类没有添加注解从而报错这样的异常
ImportTableName importTableName = (ImportTableName) clazz.getAnnotation(ImportTableName.class);
String importTable = "";
if (importTableName != null) {
importTable = importTableName.tableName();
} else {
// 如果没有注解,约定低代码平台生成的代码都是有规律的,类名和数据库名有一致性,这里的代码逻辑不再描述
}
// 可以打印一下importTable ,如果添加了自定义注解,是可以打印出来我们注解上填写的表名的
到这里我们已经获取到了自定义注解的上添加的值,我们可以根据自己的业务逻辑进行下一步操作了。