Aspect Oriented Programming(AOP)从某种意义上说是对 OOP 的补充,因为它还提供了模块化的功能。但是模块化的关键单元是方面而不是类。
AOP 将程序逻辑分为不同的部分(称为关注点)。它用于通过 跨领域关注点来提高模块化
使用
提供声明式企业服务,例如声明式事务管理。
它允许用户实现自定义 aspects。
通过 “自定义注解 + AOP” 的组合,可将校验逻辑与业务代码解耦:
示例:校验时使用
- 自定义注解:作为 “标记”,标识需要进行校验的方法或参数(如 @NeedValidation)。
1 2 3 4 5 6 7 8 9 10
| import java.lang.annotation.*;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME) public @interface NeedValidation { String[] groups() default {}; }
|
- AOP 切面:拦截被该注解标记的方法,在方法执行前调用 ValidationUtils 中的校验逻辑。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| import org.aspectj.lang.JoinPoint; 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 ValidationAspect {
@Pointcut("@annotation(needValidation)") public void validationPointcut(NeedValidation needValidation) {}
@Before("validationPointcut(needValidation)") public void doValidation(JoinPoint joinPoint, NeedValidation needValidation) { Object[] args = joinPoint.getArgs(); String methodName = joinPoint.getSignature().getName();
switch (methodName) { case "getUserById": Long userId = (Long) args[0]; ValidationUtils.validateUserId(userId); break; case "createUser": String username = (String) args[0]; ValidationUtils.validateString(username, "用户名"); break; default: throw new IllegalArgumentException("未定义方法 " + methodName + " 的校验规则"); } } }
|
- ValidationUtils:封装具体的校验规则(如参数非空、格式校验等)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| public class ValidationUtils {
public static void validateUserId(Long userId) { if (userId == null) { throw new IllegalArgumentException("用户ID不能为空"); } if (userId <= 0) { throw new IllegalArgumentException("用户ID必须为正数"); } }
public static void validateString(String param, String paramName) { if (param == null || param.trim().isEmpty()) { throw new IllegalArgumentException(paramName + "不能为空"); } }
}
|
- 在业务中使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import org.springframework.stereotype.Service;
@Service public class UserService {
@NeedValidation public String getUserById(Long userId) { return "用户信息:" + userId; }
@NeedValidation public void createUser(String username) { System.out.println("创建用户:" + username); } }
|
自定义注解本身只是一个 “标记”,无法主动执行校验逻辑。AOP 通过 “切面” 拦截被注解标记的方法,在方法执行前后插入校验代码,实现 “注解即校验” 的效果。