java自定义注解
概念:注解就是说明程序的一个标识,给计算机看的
注释:用文字描述程序,给程序员看的
定义:也叫作元数据,是一种代码级别的说明。它是 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 MapcacheMap = 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; } }