目录
前置知识:Java注解之 @Target、@Retention、@Documented简介
@Target({ElementType.TYPE}) 注解
@Retention({RetentionPolicy.Runtime}) 注解
自定义注解
在SpringBoot中,我们可以通过自定义注解来简化代码的编写和提高代码的可读性。下面是使用自定义注解的步骤:
前置知识:Java注解之 @Target、@Retention、@Documented简介
@Target({ElementType.TYPE}) 注解
表示当前注解(@CheckToken)可以打在什么东西上面,此处可以放在类上与方法上
ElementType 这个枚举类型的常量提供了一个简单的分类:注解可能出现在Java程序中的语法位置(这些常量与元注解类型(@Target)一起指定在何处写入注解的合法位置)
package java.lang.annotation;
/**
* The constants of this enumerated type provide a simple classification of the
* syntactic locations where annotations may appear in a Java program. These
* constants are used in {@link Target java.lang.annotation.Target}
* meta-annotations to specify where it is legal to write annotations of a
* given type.
* @author Joshua Bloch
* @since 1.5
* @jls 9.6.4.1 @Target
* @jls 4.1 The Kinds of Types and Values
*/
public enum ElementType {
/** 类, 接口 (包括注解类型), 或 枚举 声明 */
TYPE,
/** 字段声明(包括枚举常量) */
FIELD,
/** 方法声明(Method declaration) */
METHOD,
/** 正式的参数声明 */
PARAMETER,
/** 构造函数声明 */
CONSTRUCTOR,
/** 局部变量声明 */
LOCAL_VARIABLE,
/** 注解类型声明 */
ANNOTATION_TYPE,
/** 包声明 */
PACKAGE,
/**
* 类型参数声明
*
* @since 1.8
*/
TYPE_PARAMETER,
/**
* 使用的类型
*
* @since 1.8
*/
TYPE_USE
}
字段声明(包括枚举常量) */
FIELD,
/** 方法声明(Method declaration) */
METHOD,
/** 正式的参数声明 */
PARAMETER,
/** 构造函数声明 */
CONSTRUCTOR,
/** 局部变量声明 */
LOCAL_VARIABLE,
/** 注解类型声明 */
ANNOTATION_TYPE,
/** 包声明 */
PACKAGE,
/**
* 类型参数声明
*
* @since 1.8
*/
TYPE_PARAMETER,
/**
* 使用的类型
*
* @since 1.8
*/
TYPE_USE
}
@Retention({RetentionPolicy.Runtime}) 注解
RetentionPolicy这个枚举类型的常量描述保留注解的各种策略,它们与元注解(@Retention)一起指定注释要保留多长时间
package java.lang.annotation;
/**
* Annotation retention policy. The constants of this enumerated type
* describe the various policies for retaining annotations. They are used
* in conjunction with the {@link Retention} meta-annotation type to specify
* how long annotations are to be retained.
*
* @author Joshua Bloch
* @since 1.5
*/
public enum RetentionPolicy {
/**
* 注解只在源代码级别保留,编译时被忽略
*/
SOURCE,
/**
* 注解将被编译器在类文件中记录
* 但在运行时不需要JVM保留。这是默认的
* 行为.
*/
CLASS,
/**
*注解将被编译器记录在类文件中
*在运行时保留VM,因此可以反读。
* @see java.lang.reflect.AnnotatedElement
*/
RUNTIME
}
注解将被编译器在类文件中记录
* 但在运行时不需要JVM保留。这是默认的
* 行为.
*/
CLASS,
/**
*注解将被编译器记录在类文件中
*在运行时保留VM,因此可以反读。
* @see java.lang.reflect.AnnotatedElement
*/
RUNTIME
}
@Documented注解
Documented注解表明这个注解是由 javadoc记录的,在默认情况下也有类似的记录工具。 如果一个类型声明被注解了文档化,它的注解成为公共API的一部分。
自定义注解案例
本文以案例验证token为目的开发注解
1、pom依赖
<!--aop启动器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
2、自定义注解类
/**
* 自定义注解类
*/
//表示当前注解(@CheckToken)可以打在什么东西上面,此处可以放在类上与方法上
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME) //运行时执行
@Documented//指定被修饰的该Annotation可以被javadoc工具提取成文档
public @interface CheckToken {
// String value() default "";
}
3、切面类
/**
* 切面类
*/
@Aspect//切面注解
@Component
@SuppressWarnings({"unused"})
public class CheckTokenAspect {
//日志对象
public static final Logger logger = LoggerFactory.getLogger(CheckTokenAspect.class);
//切入点到自定义注解
@Pointcut("@annotation(com.yka.annotation.CheckToken)")
public void annotationPointcut() {
}
//前置通知
@Before("annotationPointcut()")
public void beforePointcut(JoinPoint joinPoint) throws Exception {
// 请求开始时间
ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
String token = sra.getRequest().getHeader("token");
//控制台日志打印
logger.info("token为:"+token);
if (token == null || "".equals(token)) {
throw new Exception("token为空");//报错打印
}
//校验token
}
@Around("annotationPointcut()")
public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
return joinPoint.proceed();
}
/**
* 在切入点return内容之后切入内容(可以用来对处理返回值做一些加工处理)
* @param joinPoint
*/
@AfterReturning("annotationPointcut()")
public void doAfterReturning(JoinPoint joinPoint) {
}
}
4、应用
@RestController
public class AopController {
@PostMapping("/testPost")
@CheckToken//自定义注解
public String postTest(){
return "aaaaaaaaaaaa";
}
}
5、测试
测试有token请求体,测试成功
日志打印
测试没有token请求体,测试失败
日志打印: