spring的自定义注解

在 Spring 中,自定义注解可以帮助我们实现自定义的功能,比如切面逻辑、权限控制、数据校验等。自定义注解通常结合 Spring 的 AOP 或其他功能使用,以增强业务逻辑。下面是创建自定义注解的一般步骤,以及使用示例。


一、创建自定义注解

1.1 定义自定义注解

创建一个自定义注解需要使用 @interface 关键字,同时可以添加一些元注解来控制注解的行为:

  • @Target:指定注解可以应用的位置(类、方法、字段等)。
  • @Retention:指定注解的生命周期。
  • @Documented:将注解包含在 Javadoc 中。
  • @Inherited:允许子类继承父类的注解。
示例:定义一个自定义注解 @LogExecutionTime
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Target(ElementType.METHOD) // 只能作用于方法
@Retention(RetentionPolicy.RUNTIME) // 在运行时可见
public @interface LogExecutionTime {
}

二、使用 AOP 处理自定义注解

可以通过 AOP 来处理带有 @LogExecutionTime 注解的方法,记录方法执行时间。

2.1 创建切面类

在切面类中,通过 @Around 注解拦截标注了 @LogExecutionTime 的方法,计算并打印执行时间。

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;@Aspect
@Component
public class LoggingAspect {@Around("@annotation(LogExecutionTime)")public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {long start = System.currentTimeMillis();// 执行目标方法Object proceed = joinPoint.proceed();long executionTime = System.currentTimeMillis() - start;System.out.println(joinPoint.getSignature() + " executed in " + executionTime + "ms");return proceed;}
}
2.2 在方法上使用注解

可以将 @LogExecutionTime 注解添加到任何方法上,Spring AOP 会自动拦截并记录执行时间。

import org.springframework.stereotype.Service;@Service
public class MyService {@LogExecutionTimepublic void serve() {// 模拟耗时操作try {Thread.sleep(200);} catch (InterruptedException e) {Thread.currentThread().interrupt();}System.out.println("Service executed");}
}

三、实现基于自定义注解的权限控制示例

下面示例通过自定义注解实现简单的权限控制,模拟权限验证功能。

3.1 定义权限控制注解

创建 @RoleRequired 注解,指定需要的角色。

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RoleRequired {String value(); // 指定需要的角色
}
3.2 创建权限控制的切面类

在切面类中,通过拦截 @RoleRequired 注解的方法,实现权限验证的逻辑。

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.JoinPoint;
import org.springframework.stereotype.Component;@Aspect
@Component
public class RoleAspect {// 假设当前用户角色(在实际中,这个信息可能来自上下文或会话)private static final String currentUserRole = "USER";@Before("@annotation(roleRequired)")public void checkRole(JoinPoint joinPoint, RoleRequired roleRequired) {String requiredRole = roleRequired.value();// 检查当前用户的角色if (!currentUserRole.equals(requiredRole)) {throw new SecurityException("Access Denied: insufficient permissions");}System.out.println("Access Granted: " + joinPoint.getSignature());}
}
3.3 使用权限控制注解

@RoleRequired 注解添加到需要权限控制的方法上。

import org.springframework.stereotype.Service;@Service
public class AdminService {@RoleRequired("ADMIN")public void performAdminTask() {System.out.println("Admin task performed");}
}

在运行时,如果当前用户的角色不匹配 @RoleRequired 指定的角色,将抛出异常 Access Denied: insufficient permissions


四、使用自定义注解进行参数校验

自定义注解还可以用于参数校验,结合 Spring 的 @Validated 注解,利用 AOP 实现校验逻辑。

4.1 定义注解 @NotEmpty

创建一个 @NotEmpty 注解,用于校验字段不为空。

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface NotEmpty {String message() default "Field cannot be empty";
}
4.2 创建校验器

编写 AOP 切面类,检测带有 @NotEmpty 注解的字段是否为空。

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.JoinPoint;
import org.springframework.stereotype.Component;
import java.lang.reflect.Field;@Aspect
@Component
public class ValidationAspect {@Before("execution(* com.example..*.*(..))")public void validateNotEmptyFields(JoinPoint joinPoint) throws IllegalAccessException {Object[] args = joinPoint.getArgs();for (Object arg : args) {if (arg != null) {Field[] fields = arg.getClass().getDeclaredFields();for (Field field : fields) {if (field.isAnnotationPresent(NotEmpty.class)) {field.setAccessible(true);Object value = field.get(arg);if (value == null || (value instanceof String && ((String) value).trim().isEmpty())) {NotEmpty notEmpty = field.getAnnotation(NotEmpty.class);throw new IllegalArgumentException(notEmpty.message());}}}}}}
}
4.3 使用校验注解

在实体类中使用 @NotEmpty 注解标记需要校验的字段。

public class User {@NotEmpty(message = "Username must not be empty")private String username;@NotEmpty(message = "Password must not be empty")private String password;// Constructors, getters, and setters
}
4.4 在服务中进行校验

调用带有 @NotEmpty 注解的对象时,如果字段为空,会触发校验异常。

import org.springframework.stereotype.Service;@Service
public class UserService {public void registerUser(User user) {System.out.println("User registered: " + user.getUsername());}
}

总结

自定义注解结合 AOP 可以极大地简化代码,并添加业务逻辑。以上示例展示了几种常见的自定义注解应用场景:

  • 方法执行时间记录@LogExecutionTime
  • 权限控制@RoleRequired
  • 字段校验@NotEmpty

自定义注解使代码更加简洁、可读、可复用。根据业务需求,可以灵活实现多种注解应用。

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

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

相关文章

qt QStatusBar详解

1、概述 QStatusBar是Qt框架提供的一个小部件,用于在应用程序窗口底部显示状态信息。它可以显示一些固定的文本和图标,并且可以通过API动态更新显示内容。QStatusBar通常是一个水平的窗口部件,能够显示多行文本内容,非常适合用于…

大型语言模型的运行成本分析

大型语言模型 (LLM) 一直处于生成式 AI 革命的前沿,尤其是自 ChatGPT 出现以来。然而,它们的全部潜力尚未得到释放,而一个重大障碍是成本。将 LLM 纳入应用程序的费用范围从按需用例的几美分到在云环境中托管单个 LLM 实例的每月 20,000 美元…

Spring Boot接收参数的19种方式

Spring Boot是一个强大的框架,允许开发人员通过多种方式接收和处理参数。无论是HTTP请求参数、路径变量,还是请求体中的数据,Spring Boot都能提供灵活的处理方式。本文将介绍19种不同的方式来接收参数。 1. 查询参数(Query Param…

Matlab高光谱遥感

原文链接:Matlab高光谱遥感https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247623643&idx5&sne4557ed43728f851140b100f42286988&chksmfa8da23ccdfa2b2a4d795bf4087f672faaa7082d1f52e046616ab7bf196a6eef89ea553d06b1&token1392391660&…

OPENAI官方prompt文档解析

官方文档地址:https://platform.openai.com/docs/guides/gpt-best-practices 文档中文版来源:OpenAI 官方提示工程指南 [译] | 宝玉的分享 (baoyu.io) 1.写清楚说明 如果prompt给的范围十分模糊或是过于宽泛,那么GPT就会开始猜测您想要的内容,从而导致生成的结果偏离预期. …

C++游戏开发

C游戏开发概述 C 是游戏开发中的主要编程语言之一,因其性能、控制和广泛的生态系统而受到开发者的青睐。随着游戏行业的迅速发展,C 被用来构建许多成功的游戏和游戏引擎。本文将深入探讨 C 在游戏开发中的应用,包括基础概念、技术栈、示例代…

共模噪声和差模噪声

电源芯片加上负载和不加负载输出的纹波不一样,不加负载的情况下纹波比较小。 可以测量出DCDC电源的输出电压纹波为100Khz,刚好对应电源芯片的开关频率。可以看到纹波上面有一部分的小噪声,放大后用示波器观察频率为几Mhz。 对付上面的频率比…

DevOps赋能:优化业务价值流的实战策略与路径(上)

上篇:价值流引领与可视化体系构建 一、前言 在快速迭代的软件项目和产品开发生态中,我们始终围绕两个核心目标:一是确保每一项工作都能为客户创造实际价值,这是产品团队的核心使命;二是确保这些有价值的工作能够高效…

机器学习之fetch_olivetti_faces人脸识别--基于Python实现

fetch_olivetti_faces 数据集下载 fetch_olivetti_faceshttps://github.com/jikechao/olivettifaces sklearn.datasets.fetch_olivetti_faces(*, data_homeNone, shuffleFalse, random_state0, download_if_missingTrue, return_X_yFalse, n_retries3, delay1.0)[source] L…

HTML 语法规范——代码注释、缩进与格式、标签与属性、字符编码等

文章目录 一、代码注释1.1 使用注释的主要目的1.2 使用建议二、标签的使用2.1 开始标签和结束标签2.2 自闭合标签2.3 标签的嵌套2.4 标签的有效性三、属性四、缩进与格式4.1 一致的缩进4.2 元素单独占用一行4.3 嵌套元素的缩进4.4 避免冗长的行五、字符编码六、小结在开发 HTML…

Charles简单压力测试

1.接口请求次数,并发量,请求延迟时间均可配置 1.1选中需要进行测试的接口,鼠标右键选中【repeat advance】 2.设置并发参数 下面的图中,选择了1个接口,每次迭代中1个接口同时请求,迭代1000次(…

HrmonyOS 赋能套件介绍

文章为官方教程以及自己的部分理解,用于上下班的查看学习。官方视频教程地址:HarmonyOS应用开发者基础认证-华为开发者学堂 (huawei.com) HarmonOS 赋能套件全景 感知 通过白皮书了解认识 HarmonOS 应用开发的核心理念、关键能力和创新体验 学习与评估…

Windows 下基于 CLion 配置 Linux 项目开发环境

【Windows 下基于 CLion 配置 Linux 项目开发环境 【C/C/Linux】】 https://www.bilibili.com/video/BV1tH4y1U73v/?share_sourcecopy_web&vd_source57dbd16b8c7c2ad258cccce5966c5be8

es拼音分词器(仅供自己参考)

github地址:https://github.com/infinilabs/analysis-pinyin(各种版本,对接es版本) 拼音分词器存在的问题: 1、是直接将每个字的拼音返回和一段话的拼音首字母返回,不能很好的分词。 2、不会保留中文&am…

机器人技术革新:人工智能的强力驱动

内容概要 在当今世界,机器人技术与人工智能的结合正如星星与大海,彼此辉映。随着科技的不断进步,人工智能不仅仅是为机器人赋予了“聪明的大脑”,更是推动了整个行业的快速发展。回顾机器人技术的发展历程,我们会发现…

Waymo的EMMA给多模态端到端自驾指引了方向

最近Waymo发的论文EMMA端到端确实在自动驾驶届引发了很大的关注,核心的原因是它采用的端到端模型是基于Gemini Nano的语言模型,目前看现在做端到端方案的,就它和特斯拉是语言模型为底座来实现多模态视觉输入的。 EMMA:End-to-End Multimodal…

第二十八篇——向量代数(下):如何通过向量夹角理解不同“维度”?

目录 一、背景介绍二、思路&方案三、过程1.思维导图2.文章中经典的句子理解3.学习之后对于投资市场的理解4.通过这篇文章结合我知道的东西我能想到什么? 四、总结五、升华 一、背景介绍 一个向量的夹角计算,增加了N个维度;让我的思路一下…

猫头虎分享Python 编码转换库:处理 JSONL 编码格式转换的最佳实践

猫头虎分享Python 编码转换库:处理 JSONL 编码格式转换的最佳实践 在数据处理的过程中,编码转换是一个不可避免的重要环节。特别是当我们面对来自不同来源的数据时,确保数据的编码一致性对于数据的正确解析和处理至关重要。本文将介绍 Pytho…

5. STM32之TIM实验--输出比较(PWM输出,电机,四轴飞行器,智能车,机器人)--(实验5:PWM驱动直流电机)

作者:Whappy,日期:2024.10.29,决战STM32 直流电机的控制就比较简单了,只有数据线和地线,正接正转,反接反转,为了方便,本实验采用H桥电路来控制电机的正反转,H桥电路也很简单,就是4个MOS管构成的2路推挽输出电路. 注:基本上大功率器件,单片机基本上是无法驱动的,都是要靠一部分…

微服务实战系列之玩转Docker(十六)

导览 前言Q:基于容器云如何实现高可用的配置中心一、etcd入门1. 简介2. 特点 二、etcd实践1. 安装etcd镜像2. 创建etcd集群2.1 etcd-node12.2 etcd-node22.3 etcd-node3 3. 启动etcd集群 结语系列回顾 前言 Docker,一个宠儿,一个云原生领域的…