【Spring Boot】元注解

news2024/10/27 11:51:20

元注解

  • 1.元注解
    • 1.1 @Target
    • 1.2 @Retention
    • 1.3 @Inherited
    • 1.4 @Documented
    • 1.5 @interface
  • 2.自定义注解
    • 2.1 创建自定义注解类
    • 2.2 实现业务逻辑
    • 2.3 使用自定义注解

1.元注解

元注解就是定义注解的注解,是 Java 提供的用于定义注解的基本注解。

注解
说明
@Retention是注解类,实现声明类 Class,声明类别 Category,声明扩展 Extension
@Target放在自定义注解的上边,表明该注解可以使用的范围
@Inherited允许子类继承父类的注解,在子类中可以获取使用父类注解
@Documented表明这个注释是由 Javadoc 记录的
@interface用来自定义注释类型

1.1 @Target

该注解的作用是告诉 Java 将自定义的注解放在什么地方,比如类、方法、构造器、变量上等。它的值是一个枚举类型,有如下属性值。

  • ElementType.CONSTRUCTOR:用于描述构造器。
  • ElementType.FIELD:用于描述成员变量、对象、属性(包括 enum 实例)。
  • ElementType.LOCAL_VARIABLE:用于描述局部变量。
  • ElementType.METHOD:用于描述方法。
  • ElementType.PACKAGE:用于描述包。
  • ElementType.PARAMETER:用于描述参数。
  • ElementType.TYPE:用于描述类、接口(包括注解类型)或 enum 声明。

1.2 @Retention

该注解用于说明自定义注解的生命周期,在注解中有三个生命周期。

  • RetentionPolicy.RUNTIME:始终不会丢弃,运行期也保留该注解,可以使用反射机制读取该注解的信息。自定义的注解通常使用这种方式。
  • RetentionPolicy.CLASS:类加载时丢弃,默认使用这种方式。
  • RetentionPolicy.SOURCE:编译阶段丢弃,自定义注解在编译结束之后就不再有意义,所以它们不会写入字节码。@Override@SuppressWarnings 都属于这类注解。

1.3 @Inherited

该注解是一个标记注解,表明被标注的类型是可以被继承的。如果一个使用了 @Inherited 修饰的 Annotation 类型被用于一个 Class,则这个 Annotation 将被用于该 Class 的子类。

1.4 @Documented

该注解表示是否将注解信息添加在 Java 文档中。

1.5 @interface

该注解用来声明一个注解,其中的每一个方法实际上是声明了一个配置参数。方法的名称就是参数的名称,返回值类型就是参数的类型(返回值类型只能是基本类型、Class、String、enum)。可以通过 default 来声明参数的默认值。

定义注解格式见以下代码:

public @interface 注解名{定义体}

2.自定义注解

有时需要自定义注解来快捷地实现功能。本实例演示如何自定义注解,以及实现业务逻辑处理。

2.1 创建自定义注解类

package com.example.demo;

import org.springframework.stereotype.Component;

import java.lang.annotation.*;

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface MyTestAnnotation {
    String value();
}

代码解释如下。

  • 使用 @Target 注解标注作用范围。
  • 使用 @Retention 注解标注生命周期。
  • 使用 @Documented 将注解信息添加在 Java 文档中。

2.2 实现业务逻辑

以 AOP 的方式实现业务逻辑,见以下代码:

package com.example.demo;

import org.aspectj.lang.JoinPoint;
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;

@Aspect
@Component
public class TestAnnotationAspect {
    // 拦截被 TestAnnotation 注解的方法;如果需要拦截指定 package 指定规则名称的方法,可以使用表达式 execution(...)
    @Pointcut("@annotation(com.example.demo.MyTestAnnotation)")
    public void myAnnotationPointCut() {
    }

    @Before("myAnnotationPointCut()")
    public void before(JoinPoint joinPoint) throws Throwable {
        MethodSignature sign = (MethodSignature) joinPoint.getSignature();
        Method method = sign.getMethod();
        MyTestAnnotation annotation = method.getAnnotation(MyTestAnnotation.class);
        // 获取注解参数
        System.out.print("打印TestAnnotation 参数:" + annotation.value());

    }

}

类注解

  • @Aspect:这是一个切面注解,用于标记这个类为一个切面类。切面类包含了通知(Advice),定义了要在哪些连接点(JoinPoint)上执行的逻辑。
  • @Component:这是一个组件注解,用于将这个切面类注册为 Spring 容器中的一个组件,以便 Spring 可以自动扫描并实例化它。

切入点表达式

  • @Pointcut("@annotation(com.example.demo.MyTestAnnotation)"):这是一个切入点(Pointcut)定义,用于指定这个切面要拦截的操作。这里的切入点表达式表示拦截所有被 MyTestAnnotation 注解标记的方法。

通知方法

  • public void myAnnotationPointCut() {}:这是一个空方法,被上面的 @Pointcut 标注,用来定义切入点逻辑。

前置通知

  • @Before("myAnnotationPointCut()"):这是一个前置通知,表示在切入点 myAnnotationPointCut 指定的方法(即被 MyTestAnnotation 注解的方法)执行之前运行这个通知方法。
  • public void before(JoinPoint joinPoint) throws Throwable {...}:这是实际执行的前置通知方法。在这个方法中,可以获取到被拦截方法的签名、参数等信息,并且可以执行一些自定义的逻辑。
    • MethodSignature sign = (MethodSignature) joinPoint.getSignature();:获取方法签名。
    • Method method = sign.getMethod();:获取具体的方法对象。
    • MyTestAnnotation annotation = method.getAnnotation(MyTestAnnotation.class);:获取方法上的 MyTestAnnotation 注解。
    • System.out.print("打印TestAnnotation 参数:" + annotation.value());:打印注解的参数值。

这段代码的作用是在 Spring AOP 环境下,拦截所有使用了 MyTestAnnotation 注解的方法,并在这些方法执行之前打印出注解的参数值。这种机制可以用来做很多有趣的事情,比如 日志记录权限检查性能监控 等,极大地增强了代码的灵活性和可维护性。

2.3 使用自定义注解

在需要使用的地方使用自定义注解,直接添加注解名即可,见以下代码:

package com.example.demo;

import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;

@RestController
@EnableAspectJAutoProxy
public class TestController {
    @RequestMapping("/")
    @MyTestAnnotation("测试Annotation")
    public void testAnnotation() {
        System.err.println("测试自定义注解");
    }

}

运行上面代码,输出如下结果:

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2224640.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

linux中级(NFS服务器)

NFS:用于在NNIX/Linux主机之间进行文件共享的协议 流程:首先服务端开启RPC服务,并开启111端口,服务器端启动NFS服务,并向RPC注册端口信息,客户端启动RPC,向服务器RPC服务请求NFS端口&#xff0…

Matlab数字信号处理——基于改进小波变换的图像去噪方法(7种去噪算法)

1.基于小波变换的阈值收缩法去噪 该方法利用小波变换分离出信号中的噪声成分,并通过设置合适的阈值对小波系数进行收缩,保留主要信息的同时,去除噪声。 %基于小波变换的阈值收缩法去噪算法 clear clc Iimread(nana.png); X im2double(I); …

深入理解C语言中的静态库与动态库 —— 原理与实践

引言 在 C 语言编程中,库是预编译的代码集合,用于实现特定功能,以供其他程序使用。库可以分为静态库和动态库两种主要类型。静态库在编译阶段被链接到目标程序中,而动态库则是在运行时被加载。本文旨在深入探讨这两种库的工作原理…

渗透测试-百日筑基—SQL注入篇时间注入绕过HTTP数据编码绕过—下

day8-渗透测试sql注入篇&时间注入&绕过&HTTP数据编码绕过 一、时间注入 SQL注入时间注入(也称为延时注入)是SQL注入攻击的一种特殊形式,它属于盲注(Blind SQL Injection)的一种。在盲注中,攻击…

Android 在github网站下载项目:各种很慢怎么办?比如gradle下载慢;访问github慢;依赖下载慢

目录 访问github慢gradle下载慢依赖下载慢 前言 大家好,我是前期后期,在网上冲浪的一名程序员。 为什么要看这篇文章呢?问题是什么? 我们在Github上面看到一些好的项目的时候,想下载下来研究学习一下。但经常遇到各…

外面卖几百的Ai数字人软件 说123456生成视频 去授权版本

下载:https://pan.quark.cn/s/27a0cff98eae 可以无限制使用。

网络拓扑视角下的IP地址管理优化

前言 对IP地址进行有效管理,好处是能 提升网络运行效率,还可以保障网络安全和稳定。网络拓扑结构本身作为网络描述中各节点联系的主要角色,为IP地址管理提供了一些优化策略。 网络拓扑和IP地址管理的关系 网络拓扑结构描述了网络中各节点&a…

【Spring MVC】响应结果和设置

​ 我的主页:2的n次方_ 1. 返回静态页面 先创建一个 html 页面 ​ 如果还按照之前的方式进行返回的话,返回的并不是一个 html 页面 RequestMapping("/response") RestController public class ResponseController {RequestMapping(&quo…

线程同步(互斥锁条件变量)

线程同步 互斥锁(互斥量)条件变量生产/消费者模型 一、互斥锁 C11提供了四种互斥锁: mutex:互斥锁。timed_mutex:带超时机制的互斥锁。recursive_mutex:递归互斥锁。recursive_timed_mutex:带超时机制的递归互斥锁…

命名管道和共享内存

命名管道 管道应用的一个限制就是只能在具有共同祖先的进程间通信,如果我们想在不相关的进程之间交换数据,可以使用FIFO文件来做这项工作,它被称为命名管道,命名管道是一种特殊类型的文件 创建命名管道 int main(int argc, cha…

落地台灯什么牌子好?口碑最好的落地灯品牌

落地台灯什么牌子好?随着落地台灯被越来越多的人认可,如今市场中护眼大路灯品牌类型五花八门,质量存在较大差距。很多网红、明星代言等产品,入行时间短,关注市场营销,而忽视产品核心技术的提升,…

Codeforces Round 982 div2 个人题解(A~D2)

Codeforces Round 982 div2 个人题解(A~D2) Dashboard - Codeforces Round 982 (Div. 2) - Codeforces 火车头 #define _CRT_SECURE_NO_WARNINGS 1#include <algorithm> #include <array> #include <bitset> #include <cmath> #include <cstdio&…

软件系统建设方案书(word参考模板)

1 引言 1.1 编写目的 1.2 项目概述 1.3 名词解释 2 项目背景 3 业务分析 3.1 业务需求 3.2 业务需求分析与解决思路 3.3 数据需求分析【可选】 4 项目建设总体规划【可选】 4.1 系统定位【可选】 4.2 系统建设规划 5 建设目标 5.1 总体目标 5.2 分阶段目标【可选】 5.2.1 业务目…

简记 Vue3(一)—— setup、ref、reactive、toRefs、toRef

个人简介 &#x1f440;个人主页&#xff1a; 前端杂货铺 &#x1f64b;‍♂️学习方向&#xff1a; 主攻前端方向&#xff0c;正逐渐往全干发展 &#x1f4c3;个人状态&#xff1a; 研发工程师&#xff0c;现效力于中国工业软件事业 &#x1f680;人生格言&#xff1a; 积跬步…

API网关的作用--为什么微服务需要一个API网关?

微服务网关核心作用就是协议转换、安全隔离和流量控制 微服务架构中&#xff0c;API网关作为系统的入口点&#xff0c;可以统一处理所有客户端请求。 1&#xff09;协议转换&#xff1a;它能够支持多种通信协议&#xff08;如HTTP、gRPC等&#xff09;之间的相互转换&#xff…

【数据结构】快速排序(三种实现方式)

目录 一、基本思想 二、动图演示&#xff08;hoare版&#xff09; 三、思路分析&#xff08;图文&#xff09; 四、代码实现&#xff08;hoare版&#xff09; 五、易错提醒 六、相遇场景分析 6.1 ❥ 相遇位置一定比key要小的原因 6.2 ❥ 右边为key&#xff0c;左边先走 …

一个关于@JsonIgnore的isxxx()问题

一个关于JsonIgnore的问题 版本:2.13.5 <dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><optional>true</optional></dependency>代码&#xff1a; Data public clas…

2024年10月27日历史上的今天大事件早读

公元前628年10月27日 春秋五霸之一晋文公重耳卒 1915年10月27日 美军进入一战前线 1921年10月27日 思想家严复逝世 1927年10月27日 中共创建井冈山根据地 1937年10月27日 八百壮士坚守四行仓库 1937年10月27日 伪“蒙古联盟自治政府”成立 1938年10月27日 日军对中国军队…

《向量数据库指南》——text-embedding-3-large与Mlivus Cloud打造语义搜索新纪元

使用text-embedding-3-large生成向量并将向量插入Mlivus Cloud实现高效语义搜索的深度解析与实战操作 在数字化时代,数据的处理和存储方式正在经历前所未有的变革。特别是随着大数据和人工智能技术的快速发展,向量数据库作为一种新型的数据存储和查询方式,正逐渐受到越来越…

KUKA机器人选定程序时提示“选择非法”的处理方法

KUKA机器人选定程序时提示“选择非法”的处理方法 如下图所示,选中某个程序,点击选定时, 系统提示:选择非法, 具体处理方法可参考以下内容: 选中该程序后,在右下角打开【编辑】菜单键,再选择【属性】,打开后可以看到程序的一般说明、信息模块和参数等信息,如下图所示…