玩转Spring Boot自定义注解:从入门到精通的5个实战案例
Spring Boot自定义注解是扩展框架功能的强大工具,它能简化代码、提升可维护性,并实现AOP(面向切面编程)等高级特性。本文将通过5个实战案例,从简单入门到精通进阶,逐步教你如何创建和应用自定义注解。每个案例包括:
- 描述:注解的作用和场景。
- 实现步骤:使用Spring Boot和Java代码展示。
- 解释:核心原理和注意事项。
所有代码基于Spring Boot 3.x和Java 17,确保真实可用。案例难度递增,覆盖日志记录、参数验证、事务管理、安全控制和启动配置。
案例1:入门级 - 日志记录注解(@LogExecutionTime)
描述:创建一个简单注解,用于记录方法执行时间,适合初学者理解注解定义和AOP集成。
实现步骤:
- 定义注解:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME) // 注解在运行时保留
@Target(ElementType.METHOD) // 只能应用于方法
public @interface LogExecutionTime {
}
- 创建AOP切面处理:
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 LogExecutionAspect {
@Around("@annotation(LogExecutionTime)") // 拦截@LogExecutionTime注解的方法
public Object logTime(ProceedingJoinPoint joinPoint) throws Throwable {
long startTime = System.currentTimeMillis();
Object result = joinPoint.proceed(); // 执行原方法
long endTime = System.currentTimeMillis();
System.out.println("方法 " + joinPoint.getSignature().getName() + " 执行耗时: " + (endTime - startTime) + "ms");
return result;
}
}
- 应用注解:
@Service
public class UserService {
@LogExecutionTime
public void processUserData() {
// 模拟耗时操作
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
解释:
- 原理:通过AOP的
@Around通知,在方法执行前后计算时间差。 - 优点:代码非侵入式,易于复用。
- 注意:确保Spring Boot项目已添加
spring-boot-starter-aop依赖。
案例2:基础级 - 参数验证注解(@ValidParam)
描述:扩展Spring Validation,自定义注解用于方法参数校验,适合掌握注解属性和验证器集成。
实现步骤:
- 定义注解:
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;
@Documented
@Constraint(validatedBy = NotEmptyValidator.class) // 指定验证器
@Target({ElementType.PARAMETER, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ValidParam {
String message() default "参数不能为空"; // 默认错误消息
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
- 创建验证器:
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
public class NotEmptyValidator implements ConstraintValidator<ValidParam, String> {
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
return value != null && !value.trim().isEmpty(); // 简单非空校验
}
}
- 应用注解:
@RestController
public class UserController {
@PostMapping("/user")
public ResponseEntity<String> createUser(@RequestBody @ValidParam String username) {
// 如果username为空,Spring会自动抛出MethodArgumentNotValidException
return ResponseEntity.ok("用户创建成功: " + username);
}
}
解释:
- 原理:集成Spring Validation框架,通过
ConstraintValidator实现校验逻辑。 - 优点:统一处理参数错误,减少重复代码。
- 注意:需添加
spring-boot-starter-validation依赖,并配置全局异常处理器。
案例3:中级 - 事务管理注解(@CustomTransactional)
描述:自定义简化版事务注解,结合Spring事务管理,适合学习注解属性和事务传播。
实现步骤:
- 定义注解:
import org.springframework.transaction.annotation.Transactional;
@Transactional(rollbackFor = Exception.class) // 继承Spring的@Transactional
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CustomTransactional {
int timeout() default 30; // 自定义超时属性,单位为秒
}
- 创建事务切面:
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.transaction.support.TransactionTemplate;
@Aspect
@Component
public class CustomTransactionAspect {
private final TransactionTemplate transactionTemplate;
public CustomTransactionAspect(TransactionTemplate transactionTemplate) {
this.transactionTemplate = transactionTemplate;
}
@Around("@annotation(customTx)") // 拦截@CustomTransactional注解
public Object manageTransaction(ProceedingJoinPoint joinPoint, CustomTransactional customTx) throws Throwable {
return transactionTemplate.execute(status -> {
try {
status.setTimeout(customTx.timeout()); // 设置超时
return joinPoint.proceed();
} catch (Throwable e) {
throw new RuntimeException("事务异常", e);
}
});
}
}
- 应用注解:
@Service
public class OrderService {
@CustomTransactional(timeout = 10) // 设置10秒超时
public void placeOrder() {
// 数据库操作,如超时或异常会自动回滚
}
}
解释:
- 原理:基于Spring的
TransactionTemplate,通过AOP包装事务逻辑。 - 优点:灵活控制事务属性,如超时时间。
- 注意:需要配置
DataSource和PlatformTransactionManager。
案例4:高级 - 安全控制注解(@Secure)
描述:实现基于角色的访问控制注解,集成Spring Security,适合高级用户掌握注解解析和权限验证。
实现步骤:
- 定义注解:
import java.lang.annotation.*;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Secure {
String[] roles() default {}; // 允许的角色列表
}
- 创建安全切面:
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class SecurityAspect {
@Before("@annotation(secure)") // 在方法执行前检查权限
public void checkAccess(Secure secure) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth == null || !auth.isAuthenticated()) {
throw new SecurityException("用户未认证");
}
String[] requiredRoles = secure.roles();
boolean hasRole = false;
for (String role : requiredRoles) {
if (auth.getAuthorities().stream().anyMatch(g -> g.getAuthority().equals(role))) {
hasRole = true;
break;
}
}
if (!hasRole) {
throw new SecurityException("无权限访问");
}
}
}
- 应用注解:
@RestController
public class AdminController {
@Secure(roles = {"ADMIN"}) // 仅允许ADMIN角色
@GetMapping("/admin")
public String adminDashboard() {
return "管理员面板";
}
}
解释:
- 原理:使用AOP的
@Before通知,结合Spring Security的认证上下文进行角色校验。 - 优点:细粒度控制方法级权限。
- 注意:需集成Spring Security,并配置角色管理。
案例5:精通级 - 启动配置注解(@EnableCustomFeature)
描述:创建注解用于自动配置Spring Boot启动项,类似@EnableCaching,适合精通Spring自动配置机制。
实现步骤:
- 定义注解:
import org.springframework.context.annotation.Import;
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Import(CustomFeatureConfig.class) // 导入配置类
public @interface EnableCustomFeature {
String prefix() default "custom"; // 自定义属性前缀
}
- 创建自动配置类:
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableConfigurationProperties(CustomProperties.class) // 启用属性绑定
public class CustomFeatureConfig {
@Bean
public CustomService customService(CustomProperties properties) {
return new CustomService(properties.getPrefix());
}
}
- 定义属性和服务:
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "custom") // 绑定application.yml中的属性
public class CustomProperties {
private String prefix = "default";
// Getter和Setter
public String getPrefix() { return prefix; }
public void setPrefix(String prefix) { this.prefix = prefix; }
}
public class CustomService {
private final String prefix;
public CustomService(String prefix) {
this.prefix = prefix;
}
public String process(String input) {
return prefix + "-" + input;
}
}
- 应用注解:
@SpringBootApplication
@EnableCustomFeature(prefix = "myapp") // 启动时自动配置
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
解释:
- 原理:通过
@Import导入配置类,利用Spring Boot的自动装配机制初始化Bean。 - 优点:实现模块化启动,简化配置。
- 注意:需在
src/main/resources/META-INF/spring.factories中注册自动配置类。
总结
通过这些实战案例,你已从入门到精通掌握了Spring Boot自定义注解的核心技能:
- 入门:日志记录(@LogExecutionTime) – 基础AOP应用。
- 基础:参数验证(@ValidParam) – 集成验证框架。
- 中级:事务管理(@CustomTransactional) – 自定义事务属性。
- 高级:安全控制(@Secure) – 结合Spring Security。
- 精通:启动配置(@EnableCustomFeature) – 实现自动装配。
最佳实践:
- 测试每个注解:使用JUnit和Spring Boot Test确保功能可靠。
- 逐步迭代:从简单案例开始,逐步添加复杂逻辑。
- 资源推荐:参考Spring官方文档和GitHub示例库加深理解。
通过这5个案例,你将能灵活运用自定义注解提升项目效率。如果有具体问题,欢迎进一步讨论!

1084

被折叠的 条评论
为什么被折叠?



