前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SpringBoot如何创建一个自定义注解

SpringBoot如何创建一个自定义注解

原创
作者头像
奇怪的Java
发布2024-03-17 19:55:28
2920
发布2024-03-17 19:55:28
举报
文章被收录于专栏:随心写Java

自定义注解使用场景场景

  • 日志操作
  • 权限校验
  • 参数校验
  • 缓存控制
  • 自定义逻辑业务

自定义注解需要使用到的注解说明

  • 定义注解需使用 @interface关键词 ,并在接口上注明@Rentention(...) 和@Target(...)
  • @Target:用于描述注解的使用范围,依赖于枚举类ElementType ,具体如下:
代码语言:Java
复制
public enum ElementType {

    /**用于描述类、接口(包括注解类型) 或enum声明 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

}
  • @Retention:表示该注解的生命周期,是RetentionPolicy类型的,该类型是一个枚举类型,可提供三个值选择,分别是: CLASS:注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期。 RUNTIME:注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在。 SOURCE:注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃,被编译器忽略。 生命周期关系:SOURCE < CLASS < RUNTIME
  • @Documented:指示编译器将被注解的元素的注解信息包含在生成的文档中。通常情况下,Java编译器在生成文档时不会包含注解信息,但是使用了@Documented注解后,编译器会将被注解的元素的注解信息包含在生成的文档中,这样可以使得开发者在查看文档时能够更清晰地了解被注解元素的相关信息。

自定义注解创建

 这一步就是我们需要如何去处理我们的注解,这里面有四个方法,分别是@Before、@after、@Around、AfterReturning、AfterThrowing。

  • @Before: 前置通知, 在方法执行之前执行,这个通知不能阻止连接点前的执行(除非它抛出一个异常)。
  • @After: 后置通知, 在方法执行之后执行(不论是正常返回还是异常退出)。
  • @Around: 包围一个连接点(join point)的通知,如方法调用。这是最强大的一种通知类型。 环绕通知可以在方法调用前后完成自定义的行为。它也会选择是否继续执行连接点或直接返回它们自己的返回值或抛出异常来结束执行。
  • @AfterRunning:返回通知, 在方法正常返回结果之后执行 。
  • @AfterThrowing: 异常通知, 在方法抛出异常之后。
代码语言:java
复制
import com.fs.erp.mybatis.enums.OpLogType;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 系统日志注解
 * 使用方法: 比如关于用户的日志可以分为“登录、退出登录” 此时type可以使用统一的字符串,这样可以将关于用户行为的日志全部查出 然后再根据不同的name将这些日志进一步细分
 * name同时也用于前端显示 在上述例子中,可以将type设置为“user.operation” 登录的name设置为“用户登录” 退出登录的name设置为“退出登录”
 *
 * @author 奇怪
 */
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface OpLog {

  /**
   * 日志类型 用于做业务区分
   *
   * @return
   */
  OpLogType type();

  /**
   * 日志名称 需要填充参数部分用{}占位,会根据params的值进行填充
   *
   * @return
   */
  String name() default "";

  /**
   * 需要保存的参数 Spel表达式
   *
   * @return
   */
  String[] params() default {};

  /**
   * 是否循环填充日志名称 会将params中的collection循环format
   *
   * @return
   */
  boolean loopFormat() default false;
}

定义注解的行为

代码语言:java
复制
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.expression.EvaluationContext;
import org.springframework.stereotype.Component;

import java.util.*;

/**
 * OpLog切面
 *
 * @author 奇怪
 */
@Slf4j
@Aspect
@Component
@ConditionalOnProperty(value = "op-logs.enabled", matchIfMissing = true)
public class OpLogAspector {

  @Pointcut("@annotation(OpLog)")
  public void opLogCutPoint() {

  }

  @Around(value = "opLogCutPoint(OpLog)")
  public Object opLog(ProceedingJoinPoint joinPoint) throws Throwable {
      // 具体业务
  }
}

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 自定义注解使用场景场景
    • 自定义注解需要使用到的注解说明
      • 自定义注解创建
        • 定义注解的行为
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档