当前位置: 首页 > news >正文

Spring Boot如何自定义注解?

1.什么是注解

注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。

元注解

有一些注解可以修饰其他注解,这些注解就称为元注解(meta annotation)。Java标准库已经定义了一些元注解,我们只需要使用元注解,通常不需要自己去编写元注解。

@Target

最常用的元注解是@Target。使用@Target可以定义Annotation能够被应用于源码的哪些位置:

  • 类或接口:ElementType.TYPE
  • 字段:ElementType.FIELD
  • 方法:ElementType.METHOD
  • 构造方法:ElementType.CONSTRUCTOR
  • 方法参数:ElementType.PARAMETER

例如,定义注解@Report可用在方法上,我们必须添加一个@Target(ElementType.METHOD)

@Target(ElementType.METHOD)
public @interface Report {int type() default 0;String level() default "info";String value() default "";
}

定义注解@Report可用在方法或字段上,可以把@Target注解参数变为数组{ ElementType.METHOD, ElementType.FIELD }

@Target({ElementType.METHOD,ElementType.FIELD
})
public @interface Report {...
}

实际上@Target定义的valueElementType[]数组,只有一个元素时,可以省略数组的写法。

@Retention

另一个重要的元注解@Retention定义了Annotation的生命周期:

  • 仅编译期:RetentionPolicy.SOURCE
  • 仅class文件:RetentionPolicy.CLASS
  • 运行期:RetentionPolicy.RUNTIME

如果@Retention不存在,则该Annotation默认为CLASS。因为通常我们自定义的Annotation都是RUNTIME,所以,务必要加上@Retention(RetentionPolicy.RUNTIME)这个元注解:

@Retention(RetentionPolicy.RUNTIME)
public @interface Report {int type() default 0;String level() default "info";String value() default "";
}
@Repeatable

使用@Repeatable这个元注解可以定义Annotation是否可重复。这个注解应用不是特别广泛。

@Repeatable(Reports.class)
@Target(ElementType.TYPE)
public @interface Report {int type() default 0;String level() default "info";String value() default "";
}@Target(ElementType.TYPE)
public @interface Reports {Report[] value();
}

经过@Repeatable修饰后,在某个类型声明处,就可以添加多个@Report注解:

@Report(type=1, level="debug")
@Report(type=2, level="warning")
public class Hello {
}
@Inherited

使用@Inherited定义子类是否可继承父类定义的Annotation@Inherited仅针对@Target(ElementType.TYPE)类型的annotation有效,并且仅针对class的继承,对interface的继承无效:

@Inherited
@Target(ElementType.TYPE)
public @interface Report {int type() default 0;String level() default "info";String value() default "";
}

在使用的时候,如果一个类用到了@Report

@Report(type=1)
public class Person {
}

则它的子类默认也定义了该注解:

public class Student extends Person {
}

2.代码工程

实验目的

实现统计方法执行时间的注解

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>springboot-demo</artifactId><groupId>com.et</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>annotations</artifactId><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-autoconfigure</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId></dependency><dependency><groupId>org.assertj</groupId><artifactId>assertj-core</artifactId></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjrt</artifactId></dependency><!-- fastjson --><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.21</version></dependency></dependencies>
</project>

controller

使用自定义注解@RequestTime

package com.et.annotation.controller;import com.et.annotation.RequestTime;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.HashMap;
import java.util.Map;@RestController
public class HelloWorldController {@RequestMapping("/hello")@RequestTimepublic Map<String, Object> showHelloWorld(){Map<String, Object> map = new HashMap<>();map.put("msg", "HelloWorld");return map;}
}

custom annotation

自定义@RequestTime注解

package com.et.annotation;import java.lang.annotation.*;/*** computa the excute time for the method*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface RequestTime {}

具体的拦截逻辑类

package com.et.annotation;import com.et.annotation.util.AspectUtil;
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.springframework.stereotype.Component;import java.lang.reflect.Method;@Slf4j
@Aspect
@Component
public class RequestTimeAspect {@Pointcut(value = "@annotation(com.et.annotation.RequestTime)")public void pointcut() {}@Around("pointcut()")public Object handle(ProceedingJoinPoint point) throws Throwable {Method currentMethod = AspectUtil.getMethod(point);long starttime = System.currentTimeMillis();Object result = point.proceed();long endtime = System.currentTimeMillis();long requesttime =endtime-starttime;//if(requesttime>1000){log.info(AspectUtil.getClassName(point)+"."+currentMethod.getName()+"execute time:"+requesttime+" ms");//}return result;}
}

以上只是一些关键代码,所有代码请参见下面代码仓库

代码仓库

  • https://github.com/Harries/springboot-demo(annotations)

3.测试

  1. 启动Spring Boot应用程序
  2. 访问http://127.0.0.1:8088/hello
  3. 控制台输出 日志
2024-08-10 19:30:43.670 INFO 3343 --- [nio-8088-exec-1] com.et.annotation.RequestTimeAspect : com_et_annotation_controller_HelloWorldController.showHelloWorldexecute time:41 ms

4.引用

  • https://www.baeldung.com/java-custom-annotation 
  • Spring Boot如何自定义注解? | Harries Blog™

相关文章:

Spring Boot如何自定义注解?

1.什么是注解 注解&#xff08;Annotation&#xff09;&#xff0c;也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性&#xff0c;与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面&#xff0c;用来对这些元…...

gin框架传入的gin.context参数是池化的

1. gin.context参数不但是池化的&#xff0c;而且是指针 2. 但是gin.context又实现了context的接口。因此&#xff0c;可以当作context去使用 3. 这就会导致一个很严重的问题&#xff1a; 1. 池化导致了复用后的ctx将会将之前使用的ctx中的内容进行覆盖。 2. 实现了context接…...

AWS注册是否必须使用美元银行卡

亚马逊网络服务(AWS)作为全球领先的云计算平台,吸引了众多企业和个人用户。然而,不少人在注册AWS账户时会产生疑问:是否必须使用美元银行卡?实际上,这种说法并不准确。虽然AWS的主要结算货币是美元,但用户在注册和使用过程中有多种支付方式可供选择。我们结合九河云的分析来告…...

Spring IOC 注入的3种方式

Spring IOC 注入的3种方式 1. 构造器注入&#xff08;Constructor Injection&#xff09;2. Setter方法注入&#xff08;Setter Injection&#xff09;3. 字段注入&#xff08;Field Injection&#xff09; &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路…...

无人机影像基于机器学习的遥感反演及其结果可视化,定量遥感反演结果出图,相关性分析,指标筛选,特征选择

无人机影像或者卫星遥感反演分类模型的建立&#xff0c;反演模型的可视化制图出图&#xff0c;相关性分析&#xff0c;指标筛选&#xff0c;特征选择。代码太多&#xff0c;可企鹅联系&#xff1a; 指标的相关性分析。572 特征选择&#xff0c;贡献性最大的特征。412 LAI反演&…...

Eclipse插件之Java Dependency Viewer(显示类和包的关系图)

Java Dependency Viewer 插件的作用 Eclipse插件Java Dependency Viewer是一个为Java项目提供依赖关系可视化功能的工具。 在复杂的Java项目中&#xff0c;理解和分析类与类之间、包与包之间的依赖关系是非常有用的。Java Dependency Viewer插件通过生成依赖关系图&#xff0c…...

H5小游戏出海,如何流量变现?

根据数据显示&#xff0c; 90%的轻度休闲游戏收入来自广告&#xff0c;即IAA&#xff08;In-App Advertising&#xff09;。使用这种形式进行变现的游戏类型大多以超休闲游戏为主&#xff0c;玩法简单、游戏内容轻度、风格简洁、游戏时间碎片化且即时娱乐性较高&#xff0c;收益…...

轻空间六大专利优势:引领气膜建筑新时代

在绿色建筑和科技创新的驱动下&#xff0c;轻空间不断突破传统建筑的限制&#xff0c;推出了一系列具有前瞻性和高性能的专利技术。通过这些技术&#xff0c;轻空间不仅为建筑行业注入了新动力&#xff0c;也为未来的气膜建筑设定了更高的标准。 低碳建材&#xff1a;“clearsk…...

LeetCode-day37-2940. 找到 Alice 和 Bob 可以相遇的建筑

LeetCode-day37-2940. 找到 Alice 和 Bob 可以相遇的建筑 题目描述示例示例1&#xff1a;示例2&#xff1a; 思路代码 题目描述 给你一个下标从 0 开始的正整数数组 heights &#xff0c;其中 heights[i] 表示第 i 栋建筑的高度。 如果一个人在建筑 i &#xff0c;且存在 i &…...

unity 判断平台

原文链接 Unity中判断平台的方法 Unity提供了一些方法来判断当前运行的平台&#xff0c;其中包括了判断是否为i0S平台。以下是几种常用的方法1.Application.platform Applicaion,platom 是Unity中的一个枚举类型&#xff0c;用于表示当前运行的平台。可以通过比较 Apication,p…...

PyCharm找不到Python了咋办

Python发生了重装的&#xff0c;且新的路径和原有路径不同&#xff0c;就会出现如下的错误&#xff1a; 解决办法&#xff1a; 点开PyCharm菜单的File/Setting 然后&#xff1a; 有上图的提示&#xff0c;说明需要将原来的venv进行清空。 如此操作之后&#xff0c;原来的红色…...

BRC-100 协议

BRC-100 协议 BRC-100 是一种基于序数理论的可扩展的去中心化计算协议。 BRC-100 协议会以下面的方式定义。未来所有的 BRC-100 协议栈都应该使用类似的规范来定义。 1. 摘要 BRC-100 协议是一种基于序数理论的可扩展的去中心化计算协议。 2. 抽象 BRC-100 协议本质上描述…...

茶余饭后(六)

年少成长的时候&#xff0c;多遇到一些所谓的“坏人”&#xff0c;“烂人”&#xff0c;其实是好的&#xff0c;因为这些人让你见识到了人性最丑陋的一面&#xff0c;他们让你磨炼了心性&#xff0c;在以后遇到难处理的人或事的时候&#xff0c;能够有一定的心理承受能力。遇见…...

秋招复习笔记——八股文部分:网络IP

终于来到了网络的最后一篇&#xff0c;继续加油&#xff01; IP 知识全家桶 IP 基本认识 IP 在 TCP/IP 参考模型中处于第三层&#xff0c;也就是网络层。 网络层的主要作用是&#xff1a;实现主机与主机之间的通信&#xff0c;也叫点对点&#xff08;end to end&#xff09…...

量化投资基础(四)之AR、MA、ARMA与ARIMA模型

点赞、关注&#xff0c;养成良好习惯 Life is short, U need Python 量化投资基础系列&#xff0c;不断更新中 1 引言 时间序列经典模型主要有: 自回归模型&#xff08;Auto Regressive&#xff0c;AR&#xff09;移动回归模型&#xff08;Moving Average&#xff0c;MA&…...

LVS(Linux Virtual Server)详解

LVS&#xff08;Linux Virtual Server&#xff09;是一个用于负载均衡的开源软件项目&#xff0c;旨在通过集群技术实现高性能、高可用的服务器系统。它运行在Linux操作系统上&#xff0c;并且可以利用内核级的资源来提高性能和稳定性。 思维导图 LVS的工作原理 LVS主要基于Ne…...

uniapp版本更新除了plus.runtime.getProperty的解决办法

以下是展示图 带尺寸的图片: 首先把以下代码放到想要更新弹出的页面 //template部分<uni-popup ref"popup" background-color"#fff"><versionUp handleCloseVersion"closeVersion"></versionUp></uni-popup>//script…...

MySQL笔记-基础篇(二):多表查询

​ 博客主页: 南来_北往 系列专栏&#xff1a;Spring Boot实战 前言 MySQL的多表查询是一项非常实用的数据库操作技术&#xff0c;它能够通过关联不同表中的数据来提供更加丰富和准确的信息。在实际应用中&#xff0c;数据通常不是孤立存在的&#xff0c;而是分布在多个…...

备战秋招60天算法挑战,Day15

题目链接&#xff1a; https://leetcode.cn/problems/minimum-window-substring/ 视频题解&#xff1a; https://www.bilibili.com/video/BV1sJ4m1g727/ LeetCode 76. 最小覆盖子串 题目描述 给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s …...

【学习笔记】Matlab和python双语言的学习(整数规划和0-1规划)

文章目录 前言一、整数规划和0-1规划二、典型示例1.背包问题2.指派问题 三、代码实现----Matlab1.Matlab 的 intlinprog 函数2.Matlab 代码背包问题指派问题 四、代码实现----python背包问题指派问题 总结 前言 通过模型算法&#xff0c;熟练对Matlab和python的应用。 学习视频…...

Admin.Net中的消息通信SignalR解释

定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...

OkHttp 中实现断点续传 demo

在 OkHttp 中实现断点续传主要通过以下步骤完成&#xff0c;核心是利用 HTTP 协议的 Range 请求头指定下载范围&#xff1a; 实现原理 Range 请求头&#xff1a;向服务器请求文件的特定字节范围&#xff08;如 Range: bytes1024-&#xff09; 本地文件记录&#xff1a;保存已…...

DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI

前一阵子在百度 AI 开发者大会上&#xff0c;看到基于小智 AI DIY 玩具的演示&#xff0c;感觉有点意思&#xff0c;想着自己也来试试。 如果只是想烧录现成的固件&#xff0c;乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外&#xff0c;还提供了基于网页版的 ESP LA…...

Java多线程实现之Thread类深度解析

Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...

Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)

在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马&#xff08;服务器方面的&#xff09;的原理&#xff0c;连接&#xff0c;以及各种木马及连接工具的分享 文件木马&#xff1a;https://w…...

React---day11

14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store&#xff1a; 我们在使用异步的时候理应是要使用中间件的&#xff0c;但是configureStore 已经自动集成了 redux-thunk&#xff0c;注意action里面要返回函数 import { configureS…...

R语言速释制剂QBD解决方案之三

本文是《Quality by Design for ANDAs: An Example for Immediate-Release Dosage Forms》第一个处方的R语言解决方案。 第一个处方研究评估原料药粒径分布、MCC/Lactose比例、崩解剂用量对制剂CQAs的影响。 第二处方研究用于理解颗粒外加硬脂酸镁和滑石粉对片剂质量和可生产…...

并发编程 - go版

1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程&#xff0c;系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...

4. TypeScript 类型推断与类型组合

一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式&#xff0c;自动确定它们的类型。 这一特性减少了显式类型注解的需要&#xff0c;在保持类型安全的同时简化了代码。通过分析上下文和初始值&#xff0c;TypeSc…...

探索Selenium:自动化测试的神奇钥匙

目录 一、Selenium 是什么1.1 定义与概念1.2 发展历程1.3 功能概述 二、Selenium 工作原理剖析2.1 架构组成2.2 工作流程2.3 通信机制 三、Selenium 的优势3.1 跨浏览器与平台支持3.2 丰富的语言支持3.3 强大的社区支持 四、Selenium 的应用场景4.1 Web 应用自动化测试4.2 数据…...