在Spring Boot项目中,自定义注解可以大大简化代码并提高可读性和可维护性。本文将通过三个具体场景展示如何优雅地使用自定义注解来解决实际问题。
场景一:统一的日志记录
在实际开发中,我们经常需要在方法执行前后记录日志。通过自定义注解和AOP,可以优雅地实现这一功能。
1. 创建自定义注解:
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface LogExecutionTime { }
2. 实现AOP切面:
@Aspect @Component public class LogAspect { private static final Logger logger = LoggerFactory.getLogger(LogAspect.class); @Around("@annotation(com.example.LogExecutionTime)") public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable { long start = System.currentTimeMillis(); Object proceed = joinPoint.proceed(); long executionTime = System.currentTimeMillis() - start; logger.info("{} executed in {} ms", joinPoint.getSignature(), executionTime); return proceed; } }
3. 使用自定义注解:
@RestController public class UserController { @LogExecutionTime @GetMapping("/users") public List<User> getAllUsers() { // 获取用户列表的逻辑 return userService.findAll(); } }
场景二:参数校验
在Spring Boot中,可以使用自定义注解来简化参数校验逻辑。
1. 创建自定义注解:
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) @Constraint(validatedBy = PhoneValidator.class) public @interface ValidPhone { String message() default "Invalid phone number"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
2. 实现校验逻辑:
public class PhoneValidator implements ConstraintValidator<ValidPhone, String> { private static final String PHONE_PATTERN = "^\\+?[0-9. ()-]{7,25}$"; @Override public void initialize(ValidPhone constraintAnnotation) { } @Override public boolean isValid(String phoneField, ConstraintValidatorContext context) { return phoneField != null && phoneField.matches(PHONE_PATTERN); } }
3. 使用自定义注解:
public class UserDTO { @ValidPhone private String phoneNumber; // 其他字段和getter、setter }
4. 控制器中使用参数校验:
@RestController public class UserController { @PostMapping("/users") public ResponseEntity<String> createUser(@Valid @RequestBody UserDTO userDTO, BindingResult result) { if (result.hasErrors()) { return ResponseEntity.badRequest().body(result.getAllErrors().toString()); } // 创建用户的逻辑 return ResponseEntity.ok("User created successfully"); } }
场景三:权限控制
通过自定义注解,可以简化权限控制的逻辑。
1. 创建自定义注解:
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface RequiresPermission { String value(); }
2. 实现AOP切面:
@Aspect @Component public class PermissionAspect { @Autowired private PermissionService permissionService; @Around("@annotation(requiresPermission)") public Object checkPermission(ProceedingJoinPoint joinPoint, RequiresPermission requiresPermission) throws Throwable { String permission = requiresPermission.value(); if (!permissionService.hasPermission(permission)) { throw new AccessDeniedException("Access denied"); } return joinPoint.proceed(); } }
3. 使用自定义注解:
@RestController public class UserController { @RequiresPermission("admin") @GetMapping("/admin") public ResponseEntity<String> getAdminPage() { return ResponseEntity.ok("Welcome to admin page"); } }
总结
通过自定义注解,结合Spring AOP和Validator,我们可以在Spring Boot项目中优雅地解决各种实际问题。这种方式不仅使代码更加简洁和可维护,还提高了开发效率和代码质量。希望以上的三个实例能够帮助你更好地理解和应用自定义注解。