SpringAOP切面表达式拦截

wen java案例 2

本文目录导读:

SpringAOP切面表达式拦截

  1. 切面表达式基本语法
  2. 常用拦截示例
  3. 复杂组合表达式
  4. 实战案例
  5. 常见表达式速查表
  6. 注意事项

我来详细介绍Spring AOP切面表达式的各类拦截方式。

切面表达式基本语法

execution([修饰符] 返回类型 [包名.类名.]方法名(参数) [throws 异常])

常用拦截示例

拦截所有公共方法

@Before("execution(public * *(..))")
public void beforePublicMethod() {
    // 拦截所有public方法
}

拦截指定包下所有方法

// 拦截com.example.service包及其子包下的所有方法
@Before("execution(* com.example.service..*.*(..))")
public void beforeServiceMethod() {
    // .. 表示包及其子包
}

拦截指定类所有方法

// 拦截UserServiceImpl类的所有方法
@Before("execution(* com.example.service.impl.UserServiceImpl.*(..))")
public void beforeUserServiceImpl() {
}

拦截特定方法名

// 拦截以save开头的方法
@Before("execution(* com.example.service.*.save*(..))")
public void beforeSaveMethod() {
}
// 拦截findById方法
@Before("execution(* com.example.service.*.findById(Long))")
public void beforeFindById() {
}

拦截带特定参数的方法

// 拦截第一个参数是String类型的方法
@Before("execution(* com.example.service.*.*(String, ..))")
public void beforeMethodWithStringParam() {
}
// 拦截无参方法
@Before("execution(* com.example.service.*.*())")
public void beforeNoParamMethod() {
}
// 拦截只有一个参数的方法
@Before("execution(* com.example.service.*.*(*))")
public void beforeOneParamMethod() {
}

根据注解拦截

// 拦截自定义注解@Log的方法
@Before("@annotation(com.example.annotation.Log)")
public void beforeLogAnnotation() {
}
// 拦截类上有@Controller注解的方法
@Before("@within(org.springframework.stereotype.Controller)")
public void beforeControllerMethod() {
}
// 拦截参数上有特定注解的方法
@Before("@args(com.example.annotation.Valid)")
public void beforeValidParam() {
}

复杂组合表达式

使用逻辑运算符

// 两个条件同时满足 (and可以用&&代替)
@Before("execution(* com.example.service.*.*(..)) && @annotation(com.example.annotation.Log)")
public void beforeServiceAndLog() {
}
// 满足任一条件
@Before("execution(* com.example.service.*.save*(..)) || execution(* com.example.service.*.update*(..))")
public void beforeSaveOrUpdate() {
}
// 排除某些方法
@Before("execution(* com.example.service.*.*(..)) && !execution(* com.example.service.*.find*(..))")
public void beforeNotFind() {
}

使用within限定类范围

// 拦截@Service注解的类
@Before("within(@org.springframework.stereotype.Service *)")
public void beforeServiceAnnotation() {
}
// 拦截指定包下的所有类
@Before("within(com.example.service.*)")
public void beforeServicePackage() {
}
// 拦截接口实现类
@Before("within(com.example.service.UserService+)")
public void beforeUserServiceImple() {
}

this和target的区别

// target: 匹配目标对象(被代理对象)
@Before("target(com.example.service.UserService)")
public void beforeTarget() {
}
// this: 匹配代理对象
@Before("this(com.example.service.UserService)")
public void beforeThis() {
}
// 区别:当使用CGLIB代理时,this和target可能不同

实战案例

统一日志切面

@Component
@Aspect
public class LogAspect {
    // 定义通用切点
    @Pointcut("execution(* com.example.service.*.*(..))")
    public void serviceMethod() {}
    @Pointcut("@annotation(com.example.annotation.Log)")
    public void logAnnotation() {}
    // 组合使用
    @Before("serviceMethod() && logAnnotation()")
    public void beforeLog(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("执行方法: " + methodName);
    }
}

性能监控切面

@Component
@Aspect
public class PerformanceAspect {
    @Around("execution(* com.example.service.*.*(..)) && !execution(* com.example.service.*.get*(..))")
    public Object measurePerformance(ProceedingJoinPoint joinPoint) throws Throwable {
        long start = System.currentTimeMillis();
        Object result = joinPoint.proceed();
        long end = System.currentTimeMillis();
        System.out.println(joinPoint.getSignature() + " 执行时间: " + (end - start) + "ms");
        return result;
    }
}

权限校验切面

@Component
@Aspect
@Order(1)  // 控制切面执行顺序
public class AuthAspect {
    @Around("@annotation(com.example.annotation.RequireRole)")
    public Object checkRole(ProceedingJoinPoint joinPoint, RequireRole requireRole) throws Throwable {
        String[] roles = requireRole.value();
        // 获取当前用户角色
        String currentRole = getCurrentUserRole();
        if (Arrays.asList(roles).contains(currentRole)) {
            return joinPoint.proceed();
        }
        throw new SecurityException("权限不足");
    }
}

常见表达式速查表

表达式 含义
execution(* *(..)) 所有方法
execution(public * *(..)) 所有public方法
execution(* com.example..*.*(..)) 指定包及其子包所有方法
bean(userService) 指定bean名称
@annotation(org.springframework.web.bind.annotation.GetMapping) 有指定注解的方法
within(com.example.service.*) 指定包内的所有类
args(String, ..) 第一个参数为String
this(com.example.service.UserService) 代理对象是UserService类型
target(com.example.service.UserService) 目标对象是UserService类型

注意事项

  1. 性能影响:过于复杂的表达式可能影响性能
  2. 顺序问题:多个切面使用@Order控制顺序
  3. 通配符使用:匹配任意字符,匹配任意参数或包路径
  4. 使用Pointcut:建议将通用表达式定义为@Pointcut复用

这样就可以根据实际需求灵活配置AOP切面表达式了!

抱歉,评论功能暂时关闭!