俯拾皆是的Java注解,你真的get了吗?
注解是一种元数据,可以应用到代码的多种元素上,比如类、字段、方法等,它提供了关于这些元素的额外信息,但不会影响程序的运行逻辑。它主要有以下这些作用:
生成文档:另外,@Documented修饰的元素将会包含在生成的Java文档中。

JDK本身自带了一些常用的注解,主要有以下这些:

而应用于其他注解的注解,我们称之为元注解,一共有五种元注解:

我们通过两个简单的案例来实际说明一下注解的用法。
1. 通过反射读取注解信息
首先我们定义一个简单的注解,它具有name和desc两个属性,然后在定义类的时候使用这个注解,并指定属性的值,最后在测试类中获取注解信息并打印:
package com.sample.core.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
// 自定义一个注解,有value有desc两个属性
// 运行时生效,可应用于类、接口或者枚举
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyAnnotation {
String value();
String desc();
} package com.sample.core.annotation;
@MyAnnotation(value = "full-stack", desc = "欢迎来到编程世界")
public class MyClass {
} package com.sample.core.annotation;
// 通过反射获取注解的信息
public class AnnotationTest {
public static void main(String[] args) {
Class<MyClass> myClass = MyClass.class;
MyAnnotation myAnnotation = myClass.getAnnotation(MyAnnotation.class);
System.out.println(myAnnotation.value());
System.out.println(myAnnotation.desc());
}
} package com.fullstack.commerce.user.util;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyLog {
// 日志级别
String level();
} 然后再定义一个注解处理器:
package com.fullstack.commerce.user.util;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
// 这是一个切面类,同时交由Spring统一管理
@Aspect
@Component
public class MyLogAspect {
// 配置织入点
@Pointcut("@annotation(MyLog)")
private void logPointCut(){}
// 环绕织入,在调用方法的前后执行
@Around("logPointCut()")
public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
// 获取方法名称
MethodSignature signature =(MethodSignature) joinPoint.getSignature();
String methodName=signature.getName();
// 获取注解MyLog的参数值
Method method = signature.getMethod();
MyLog myLog=method.getAnnotation(MyLog.class);
String level=myLog.level();
// 打印日志
System.out.println("方法名为:"+methodName+",日志级别为:"+level);
long start = System.currentTimeMillis();
// 注解方法继续执行
Object result=joinPoint.proceed();
System.out.println("方法的执行时间为:" + (System.currentTimeMillis()-start)+"毫秒。");
return result;
}
}
这样,统一打印日志的自定义注解就定义好了,接下来就是使用了。只需要在方法上加上@MyLog的注解,并指定它的level属性值,方法在被调用时,就会自动打印日志,并在方法执行完成后,打印出方法的执行时间。我们在Controller的方法上加上这个注解,并且访问这个方法,看看结果会是如何:
package com.fullstack.commerce.user.controller;
import com.fullstack.commerce.user.util.MyLog;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("hello")
public class HelloController {
@GetMapping("test")
@MyLog(level = "info")
public String test(){
return "Hello World";
}
}
在浏览器里面输入:http://localhost:8080/hello/test,然后可以看到控制台输出如下:

以上基于JDK8实现。另外,文章主要是讲解自定义注解的使用,省去很多无关的细节,在实际代码编写中,还需要根据业务场景的实际特点做相应的丰富和改进。
都看到这里了,请帮忙一键三连啊,也就是点击文末的在看、点赞、分享,这样会让我的文章让更多人看到,也会大大地激励我进行更多的输出,谢谢!
https://docs.oracle.com/javase/tutorial/java/annotations/index.html
推荐阅读:
评论
