0
点赞
收藏
分享

微信扫一扫

自定义注解

君之言之 2022-05-23 阅读 76

概念:注解就是说明程序的一个标识,给计算机看的

注释:用文字描述程序,给程序员看的

定义:也叫作元数据,是一种代码级别的说明。它是 ​​JDK1.5​​ 引入的一个新特性,是一种特殊的接口。它可以声明在类、字段、方法、变量、参数、包等前面,作为一个描述去使用

作用分类:

  • 编写文档:通过代码中标识的注解生成文档(Swagger)
  • 代码分析:通过代码里的注解对代码进行分析(逻辑判断)
  • 编译检查:通过代码里对应的注解让编译器实现基本的编译检查(Override,Deprecated,FunctionalInterface)

JDK 中预定义的一些注解

  • Override:检测该注解标识的方法是否继承自父类
  • Deprecated:标识方法、类、字段等已经过时,后续的版本可能会将其移除
  • SuppressWarnings:压制警告

自定义注解

格式语法如下:

元注解
public @interface 注解名称{
属性列表
}

本质:注解本质上是一个接口,该接口事实上默认继承自 ​​Annotation​​ 接口

属性

事实上是接口中的抽象方法

  • 如果定义了属性,在使用属性的时候需要给属性赋值
  • 如果只有一个属性需要赋值,并且这个属性名称是​​value​​​,则可以省略​​value​
  • 数组赋值时,需要使用​​{}​​ 包起来。如果数组中只有一个元素,则大括号可以省略属性中的返回值类型有下列取值

基本数据类型、String、枚举、注解

元注解

用于描述注解的注解

注解名称

作用

@Target

描述该注解的作用范围

@Retention

描述注解被保留的阶段

@Documented

描述注解是否被抽取到 api 文档中

@Inherited

描述注解是否可以被继承

@Target的ElementType属性取值如下:

  • Type:作用于类
  • METHOD:作用于方法
  • FIELD:作用于字段

@Retention的RetentionPolicy.RUNTIME:代表当前描述的注解,会保留到 class 字节码文件中,并被 jvm 读取到

案例

编写一个缓存注解,该注解用于缓存指定方法的返回值

public final class CacheUtils {

/**
* HashMap 是线程不安全的,这里应该用 ConcurrentHashMap
*/
private static Map<String, Object> cacheMap = new ConcurrentHashMap<>();

private CacheUtils() {
}

/**
* 执行当前指定对象的指定方法
*
* @param obj 对象
* @param methodName 执行的方法名称
* @param params 参数
* @return 方法执行之后的结果
*/
public static Object invokeMethod(Object obj, String methodName, Object... params) {
Class<?> objClass = obj.getClass();
Object result = null;

try {
Method method;
if (params.length > 0) {
Class<?>[] classArr = new Class[params.length];
Object[] valueArr = new Object[params.length];
for (int i = 0; i < params.length; i++) {
classArr[i] = params[i].getClass();
valueArr[i] = params[i];
}
method = objClass.getDeclaredMethod(methodName, classArr);

// 获取缓存注解
Cache cacheAnnotation = method.getAnnotation(Cache.class);
// 先判断注解是否为空
if (cacheAnnotation != null) {
// 方法有参数,以第一个参数为小key。
Object paramsKey = params[0];

// 获取大key
String key = cacheAnnotation.key();

// 拼接key
String cacheKey = key + "." + paramsKey;

// 获取缓存
Object cacheValue = cacheMap.get(cacheKey);

// 判断缓存是否存在,如果存在,直接返回缓存的值
if (cacheValue != null) {
return cacheValue;
}
}
method.setAccessible(true);
result = method.invoke(obj, valueArr);

// 方法执行完了,将数据放入到缓存中
if (cacheAnnotation != null) {

// 获取key
// 方法有参数,以第一个参数为小key。
Object paramsKey = params[0];

// 获取大key
String key = cacheAnnotation.key();

// 拼接key
String cacheKey = key + "." + paramsKey;
cacheMap.put(cacheKey, result);
}
} else {
method = objClass.getDeclaredMethod(methodName);

// 获取缓存注解
Cache cacheAnnotation = method.getAnnotation(Cache.class);

// 先判断注解是否为空
if (cacheAnnotation != null) {

// 获取大key
String key = cacheAnnotation.key();

// 获取缓存
Object cacheValue = cacheMap.get(key);

// 判断缓存是否存在,如果存在,直接返回缓存的值
if (cacheValue != null) {
return cacheValue;
}
}
method.setAccessible(true);
result = method.invoke(obj);

// 方法执行完了,将数据放入到缓存中
if (cacheAnnotation != null) {
String key = cacheAnnotation.key();
cacheMap.put(key, result);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
}




举报

相关推荐

0 条评论