注解的定义
注解通过@interface定义
public @interface Log {
}
它的关键字和接口定义方式差不多,只不过前面多了一个@符号
注解的应用
注解的应用方式很简单在类或者方法的上方加一@xx就好了,具体的后面讲
public class Controller {
@Log
public void test(){
}
}
@Log
public class Controller {
public void test(){
}
}
元注解
元注解:就是定义注解的注解,是一种基本的注解可以定义到注解上的注解
@Retention
用来说明注解的生命周期
@Retention(RetentionPolicy.SOURCE) 注解只在源码阶段保留,编译期就被丢弃了
@Retention(RetentionPolicy.CLASS) 默认策略,注解只被保留到编译进行的时候,它并不会被加载到 JVM 中。
@Retention(RetentionPolicy.RUNTIME) 注解可以保留到程序运行的时候,它会被加载进入到 JVM 中,所以程序运行时也可以获取到它。
@Documented
Documented注解表明这个注释是由 javadoc记录的,在默认情况下也有类似的记录工具。 如果一个类型声明被注释了文档化,它的注释成为公共API的一部分。
@Target说明注解的作用目标
@Target(ElementType.TYPE) 接口、类、枚举、注解
@Target(ElementType.FIELD) 字段、枚举的常量
@Target(ElementType.METHOD) 方法
@Target(ElementType.PARAMETER) 方法参数
@Target(ElementType.CONSTRUCTOR) 构造函数
@Target(ElementType.LOCAL_VARIABLE) 局部变量
@Target(ElementType.ANNOTATION_TYPE) 注解
@Target(ElementType.PACKAGE) 包
@Inherited
@Inherited:如果一个使用了此注解的注解1,被一个class使用,那么这个注解1也对class的子类生效。例如:
@Inherited
@Target(ElementType.METHOD)
public @interface Log {
}
@Log
public class testA(){}
public class testB() extends testA{}
testA应用了@Log这个注解,那么testB这个类上面也有@Log这个注解。
@Repeatable
例如:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Logs {
Log[] value();
}
@Repeatable(Logs.class)
public @interface Log{
String descr() default "";
}
public class Controller {
@Log(descr="描述1")
@Log(descr="描述2")
public void test(){
}
}
public class LogRunner {
public static void main(String []args) throws Exception{
System.out.println("开始时间:"+new Date());
Class classs=Controller.class;
Method[] ms=classs.getMethods();
for(Method method:ms){
boolean flag=method.isAnnotationPresent(Logs.class);
if(flag){
Logs logs=method.getAnnotation(Logs.class);
for(Log log:logs.value()){
System.out.println(log.descr());
}
}
}
}
}
输出的时候就会输出,描述1,描述2.
实现自定义注解
第一步先定义一个注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface Log {
String methodName() default "defaultAMethod";
String controller() default "defaultController";
String descr() default "defaultDescr";
}
第二步应用这个注解
public class Controller {
@Log
public void test(){
System.out.println("结束时间:"+new Date());
}
}
第三步通过反射让这个注解起作用
public class LogRunner {
public static void main(String []args) throws Exception{
System.out.println("开始时间:"+new Date());
Class classs=Controller.class;
Method[] ms=classs.getMethods();
for(Method method:ms){
boolean flag=method.isAnnotationPresent(Log.class);
if(flag){
Log log=method.getAnnotation(Log.class);
System.out.println(log.methodName());
System.out.println(log.descr());
System.out.println(log.controller());
method.invoke(classs.newInstance(),null);
}
}
}
}
输出
如果将第二步方法上面的注解不使用默认的value,将代码改成
public class Controller {
@Log(methodName = "test",controller = "testController",descr = "测试")
public void test(){
System.out.println("结束时间:"+new Date());
}
}
那么将会输出