注解简单知识
关键字
自定义注解的关键字是@interface
参数类型
自定义注解的参数类型:八大基础类型、String、枚举、注解,还可以是以上类型对应的数组
如果只有一个成员变量,名字叫value
注解赋值
如果定义了成员变量,必须要给成员变量赋值 @MyAnnotation(value="")
如果只有一个成员变量,且成员变量的名称是value,可以省略value@MyAnnotation("")
如果成员变量给定默认值,可以不用再次赋值
一个注解的内部可以不定义成员变量的(@override)
定义了成员变量的注解叫元数据
没有定义成员变量的注解叫标记
元注解
用于修饰其他注解的注解
@Retention
值是一个枚举类型
用于声明生命周期
SOURCE:生命周期只在源文件中,编译器直接丢弃这种策略的注释,在.class文件中不会保留注解信息
CLASS:在字节码文件中有效,默认
RUNTIME:运行时有效,当运行Java程序时,JVM会保留注释,加载在内存中,程序可以通过反射获取该注释
@TARGET
用于指定被修饰的注解能用于修饰哪些程序元素
包含一个value的成员变量
值
public enum ElementType {/** Class, interface (including annotation type), or enum declaration */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
}
@Document
用于指定被该元注解修饰的注解类将被javadoc工具提取成文档。默认情况下,javadoc时不包括注解的,但是加上了这个注解生成的文档中就带着注解了
Document注解修饰了Deprecated注解,那么 Deprecated注解就会在javadoc提取的时候,提取到API中
@Inherited
被它修饰的注解具有继承性,如果有个类使用了被@Inherited修饰的注解,那么它的子类也将具有该注解
aop实现自定义注解
添加依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency>
写需要的注解
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface LogAnnotation {/** 请求类型 */String reqType();/** 接口类型 */String apiType();
}
定义切面
@Aspect
@Component
public class LogAspect {@Around("@annotation(logAnnotation)")public Object around(ProceedingJoinPoint point, LogAnnotation logAnnotation) throws Throwable{// 类名String className = point.getTarget().getClass().getName();// 方法名String methodName = point.getSignature().getName();// 开始时间long startTime = System.currentTimeMillis();// 执行方法 proceed就是返回值Object proceed = point.proceed();// 结束时间long endTime = System.currentTimeMillis();// 获取入参String args = JSON.toJSONString(point.getArgs()[0]);// 获取注解中apiType的值String apiType = logAnnotation.apiType();System.out.println("类名:" + className + ";方法名:" + methodName + ";开始时间:" + startTime + ";结束时间:" + endTime);System.out.println("入参:" + args + ";返回值:" + proceed + ";注解参数apiType:"+ apiType);// 获取签名Signature signature = point.getSignature();if(signature instanceof MethodSignature){MethodSignature methodSignature = (MethodSignature) signature;// 参数名称String[] properties = methodSignature.getParameterNames();System.out.println("参数名称:" + Arrays.toString(properties));// 返回类型Class<?> methodReturnType = methodSignature.getReturnType();System.out.println("返回类型:" + methodReturnType);}return proceed;}}
测试:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class TestAnnotation {@AutowiredServiceImpl service;@Testpublic void test(){service.jieshao("zhangsan",19);}
}class Student{public Student(String name, Integer age){this.name = name;this.age = age;}String name;Integer age;@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}
}@Service
class ServiceImpl{@LogAnnotation(reqType = "请求类型", apiType = "api类型")public Student jieshao(String name, Integer age){Student student = new Student(name, age);return student;}
}