欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 教育 > 幼教 > Spring Boot中自定义注解的创建与使用

Spring Boot中自定义注解的创建与使用

2025/5/9 19:27:41 来源:https://blog.csdn.net/interest_ing_/article/details/147009891  浏览:    关键词:Spring Boot中自定义注解的创建与使用

🌟 前言

欢迎来到我的技术小宇宙!🌌 这里不仅是我记录技术点滴的后花园,也是我分享学习心得和项目经验的乐园。📚 无论你是技术小白还是资深大牛,这里总有一些内容能触动你的好奇心。🔍

  • 🤖 洛可可白:个人主页

  • 🔥 个人专栏:✅前端技术 ✅后端技术

  • 🏠 个人博客:洛可可白博客

  • 🐱 代码获取:bestwishes0203

  • 📷 封面壁纸:洛可可白wallpaper

在这里插入图片描述

Spring Boot中自定义注解的创建与使用

  • Spring Boot中自定义注解的创建与使用
    • 一、什么是自定义注解?
    • 二、创建自定义注解
      • (一)定义注解
      • (二)注解的元注解
      • (三)注解的属性
    • 三、使用自定义注解
      • (一)在Spring中使用自定义注解
        • 1. 创建自定义注解
        • 2. 创建切面类
        • 3. 使用自定义注解
      • (二)通过反射获取注解信息
        • 1. 定义注解
        • 2. 使用注解
        • 3. 通过反射获取注解信息
    • 四、自定义注解的高级用法
      • (一)注解的组合
      • (二)注解的继承
      • (三)注解的动态处理
    • 五、实际应用场景
      • (一)日志记录
        • 示例:记录方法的调用信息
      • (二)权限校验
        • 示例:定义一个`@RequiresPermission`注解
        • 创建切面类处理权限校验
        • 使用`@RequiresPermission`注解
      • (三)性能监控
        • 示例:定义一个`@MonitorPerformance`注解
        • 创建切面类处理性能监控
        • 使用`@MonitorPerformance`注解
    • 六、最佳实践
      • (一)合理使用注解
      • (二)结合AOP使用
      • (三)避免滥用反射
    • 七、总结

Spring Boot中自定义注解的创建与使用

在Spring Boot中,自定义注解是一种强大的工具,它可以帮助我们实现代码的解耦、增强代码的可读性和可维护性。通过自定义注解,我们可以在代码中添加特定的标记,Spring框架可以识别这些标记并执行相应的逻辑。本文将详细介绍如何在Spring Boot中创建和使用自定义注解。

一、什么是自定义注解?

注解(Annotation)是Java语言中的一种元数据形式,它为程序元素(如类、方法、字段等)提供了一种附加信息的机制。自定义注解是指开发者根据自己的需求定义的注解。通过自定义注解,可以在代码中添加特定的标记,Spring框架可以识别这些标记并执行相应的逻辑。

二、创建自定义注解

(一)定义注解

自定义注解的定义需要使用@interface关键字。以下是一个简单的自定义注解@Log的定义:

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 Log {String operation() default ""; // 定义注解的属性,这里是一个字符串类型的属性
}

(二)注解的元注解

在定义自定义注解时,通常会使用一些元注解来指定注解的特性和行为:

  • @Target:指定注解可以使用的范围,例如类、方法、字段等。常用的值包括:

    • ElementType.TYPE:可以用于类、接口或枚举。
    • ElementType.METHOD:可以用于方法。
    • ElementType.FIELD:可以用于字段。
    • ElementType.PARAMETER:可以用于方法参数。
  • @Retention:指定注解的保留策略,即注解在什么阶段可用。常用的值包括:

    • RetentionPolicy.SOURCE:注解仅在源代码阶段保留,编译时会被丢弃。
    • RetentionPolicy.CLASS:注解在编译阶段保留,但在运行时不可用。
    • RetentionPolicy.RUNTIME:注解在运行时保留,可以通过反射获取。
  • @Documented:表示注解应该被Javadoc工具记录。

  • @Inherited:表示注解可以被子类继承。

(三)注解的属性

注解可以定义属性,这些属性可以在注解使用时提供具体的值。属性的定义类似于接口中的方法定义。例如:

public @interface Log {String operation() default ""; // 字符串类型的属性boolean enabled() default true; // 布尔类型的属性
}

三、使用自定义注解

(一)在Spring中使用自定义注解

在Spring框架中,可以通过AOP(面向切面编程)来处理自定义注解。以下是一个完整的示例,展示如何使用自定义注解@Log来记录方法的调用信息。

1. 创建自定义注解
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 Log {String operation() default "";
}
2. 创建切面类

使用@Aspect注解定义一个切面类,拦截带有@Log注解的方法,并记录日志:

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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;import java.lang.reflect.Method;@Aspect
@Component
public class LogAspect {private static final Logger logger = LoggerFactory.getLogger(LogAspect.class);// 定义切入点,拦截带有@Log注解的方法@Pointcut("@annotation(Log)")public void logPointCut() {}// 环绕通知,记录方法的调用信息@Around("logPointCut()")public Object around(ProceedingJoinPoint joinPoint) throws Throwable {long startTime = System.currentTimeMillis();// 获取方法上的注解MethodSignature signature = (MethodSignature) joinPoint.getSignature();Method method = signature.getMethod();Log logAnnotation = method.getAnnotation(Log.class);// 执行方法Object result = joinPoint.proceed();long timeTaken = System.currentTimeMillis() - startTime;logger.info("Method: {}, Operation: {}, Time Taken: {} ms",method.getName(), logAnnotation.operation(), timeTaken);return result;}
}
3. 使用自定义注解

在需要记录日志的方法上添加@Log注解:

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class UserController {@Log(operation = "查询用户信息")@GetMapping("/user")public String getUser() {return "User Data";}
}

(二)通过反射获取注解信息

除了在Spring框架中使用AOP处理注解外,还可以通过反射机制直接获取注解信息。以下是一个示例:

1. 定义注解
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 Log {String operation() default "";
}
2. 使用注解
public class UserService {@Log(operation = "查询用户信息")public String getUser() {return "User Data";}
}
3. 通过反射获取注解信息
import java.lang.reflect.Method;public class AnnotationProcessor {public static void main(String[] args) throws NoSuchMethodException {Method method = UserService.class.getMethod("getUser");if (method.isAnnotationPresent(Log.class)) {Log logAnnotation = method.getAnnotation(Log.class);System.out.println("Operation: " + logAnnotation.operation());}}
}

四、自定义注解的高级用法

(一)注解的组合

可以定义一个注解组合多个注解。例如,定义一个@Loggable注解,组合了@Log@Transactional

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.transaction.annotation.Transactional;@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Transactional
public @interface Loggable {String operation() default "";
}

然后在方法上使用@Loggable注解:

@Loggable(operation = "查询用户信息")
public String getUser() {return "User Data";
}

(二)注解的继承

虽然注解本身不能直接继承,但可以通过组合注解来实现类似的效果。例如,定义一个@BaseLog注解,然后在其他注解中使用它:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface BaseLog {String operation() default "";
}@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@BaseLog
public @interface Log {String operation() default "";
}

(三)注解的动态处理

在Spring框架中,可以通过@Bean注解和BeanPostProcessor接口动态处理注解。例如,定义一个@MyBean注解,并通过BeanPostProcessor动态注册Bean:

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyBean {
}@Configuration
public class MyBeanConfig {@Beanpublic BeanPostProcessor myBeanPostProcessor() {return new BeanPostProcessor() {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {Class<?> beanClass = bean.getClass();if (beanClass.isAnnotationPresent(MyBean.class)) {System.out.println("Bean " + beanName + " is annotated with @MyBean");}return bean;}};}
}@MyBean
public class MyService {public void doSomething() {System.out.println("Doing something...");}
}

五、实际应用场景

(一)日志记录

日志记录是自定义注解最常见的应用场景之一。通过自定义注解,我们可以方便地在方法调用前后插入日志逻辑,而无需在每个方法中手动编写日志代码。这不仅减少了代码冗余,还提高了代码的可维护性。

示例:记录方法的调用信息

在前面的示例中,我们已经展示了如何通过@Log注解记录方法的调用信息。这种方法特别适用于需要对系统操作进行审计的场景,例如记录用户的操作行为、方法的执行时间等。

(二)权限校验

在许多应用程序中,某些方法可能需要特定的权限才能执行。通过自定义注解,我们可以方便地实现权限校验逻辑,而无需在每个方法中手动编写权限校验代码。

示例:定义一个@RequiresPermission注解
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 RequiresPermission {String value();
}
创建切面类处理权限校验
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;@Aspect
@Component
public class PermissionAspect {@Pointcut("@annotation(RequiresPermission)")public void permissionPointCut() {}@Before("permissionPointCut()")public void checkPermission(JoinPoint joinPoint) {MethodSignature signature = (MethodSignature) joinPoint.getSignature();Method method = signature.getMethod();RequiresPermission annotation = method.getAnnotation(RequiresPermission.class);String requiredPermission = annotation.value();// 模拟权限校验逻辑if (!hasPermission(requiredPermission)) {throw new SecurityException("Access denied: " + requiredPermission);}}private boolean hasPermission(String permission) {// 实际应用中,这里可以调用权限服务进行校验return true; // 示例中直接返回true}
}
使用@RequiresPermission注解
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class AdminController {@RequiresPermission("ADMIN_ACCESS")@GetMapping("/admin/data")public String getAdminData() {return "Admin Data";}
}

(三)性能监控

在一些对性能要求较高的系统中,我们可能需要监控某些方法的执行时间。通过自定义注解,我们可以方便地实现性能监控逻辑,而无需在每个方法中手动编写性能监控代码。

示例:定义一个@MonitorPerformance注解
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 MonitorPerformance {
}
创建切面类处理性能监控
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;@Aspect
@Component
public class PerformanceAspect {@Pointcut("@annotation(MonitorPerformance)")public void performancePointCut() {}@Around("performancePointCut()")public Object monitorPerformance(ProceedingJoinPoint joinPoint) throws Throwable {long startTime = System.currentTimeMillis();Object result = joinPoint.proceed();long timeTaken = System.currentTimeMillis() - startTime;System.out.println("Method: " + joinPoint.getSignature().getName() + " took " + timeTaken + " ms");return result;}
}
使用@MonitorPerformance注解
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class DataService {@MonitorPerformance@GetMapping("/data")public String getData() {// 模拟耗时操作Thread.sleep(1000);return "Data";}
}

六、最佳实践

(一)合理使用注解

虽然自定义注解非常强大,但过度使用可能会导致代码难以理解和维护。因此,在使用自定义注解时,应遵循以下原则:

  • 明确注解的用途:每个注解应该有明确的用途,避免注解的功能过于复杂。
  • 保持注解的简洁性:注解的定义应该尽量简洁,避免过多的属性。
  • 合理使用元注解:根据注解的用途,合理选择@Target@Retention等元注解。

(二)结合AOP使用

在Spring框架中,自定义注解通常与AOP结合使用。通过AOP,我们可以在不修改业务逻辑代码的情况下,插入额外的逻辑(如日志记录、权限校验等)。这种解耦的方式不仅提高了代码的可维护性,还增强了代码的可扩展性。

(三)避免滥用反射

虽然反射可以动态获取注解信息,但反射的性能开销较大,且代码可读性较差。因此,在使用反射时,应尽量避免滥用。在Spring框架中,优先使用AOP来处理注解逻辑。

七、总结

自定义注解是Java和Spring框架中一个非常强大的功能,它可以帮助我们实现代码的解耦、增强代码的可读性和可维护性。通过定义自定义注解,我们可以在代码中添加特定的标记,Spring框架可以识别这些标记并执行相应的逻辑。本文通过多个实际应用场景,展示了如何在Spring Boot中创建和使用自定义注解。

希望本文对你理解和使用自定义注解有所帮助。如果你有任何问题或建议,欢迎在评论区留言,我们一起交流学习!

如果对你有帮助,点赞👍、收藏💖、关注🔔是我更新的动力!👋🌟🚀

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词