以下是Spring AOP中为所有类型通知传递参数的完整示例,包含详细注释和参数传递方式:
// 1. 目标类(被增强的类)
package com.example;
public class TargetService {
public void doTask(String param) {
System.out.println("执行业务逻辑,参数:" + param);
}
public void doTaskWithoutParam() {
System.out.println("执行无参业务逻辑");
}
public void doTaskWithError() throws Exception {
System.out.println("执行会抛异常的逻辑");
throw new RuntimeException("模拟异常");
}
}
// 2. 切面类(包含所有通知类型)
package com.example;
import org.aspectj.lang.*;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class ParameterAspect {
// 前置通知:通过JoinPoint获取参数
@Before("execution(* com.example.TargetService.*(..))")
public void beforeAdvice(JoinPoint joinPoint) {
System.out.println("前置通知:方法开始");
Object[] args = joinPoint.getArgs();
for (Object arg : args) {
System.out.println("参数值:" + arg);
}
}
// 后置通知:返回值和参数
@AfterReturning(
pointcut = "execution(* com.example.TargetService.*(..))",
returning = "result"
)
public void afterReturningAdvice(JoinPoint joinPoint, Object result) {
System.out.println("后置通知:方法正常返回");
System.out.println("返回值:" + result);
System.out.println("参数列表:" + joinPoint.getArgs());
}
// 异常通知:捕获异常和参数
@AfterThrowing(
pointcut = "execution(* com.example.TargetService.*(..))",
throwing = "ex"
)
public void afterThrowingAdvice(JoinPoint joinPoint, Throwable ex) {
System.out.println("异常通知:方法抛出异常");
System.out.println("异常信息:" + ex.getMessage());
System.out.println("异常发生时的参数:" + joinPoint.getArgs());
}
// 环绕通知:直接操作ProceedingJoinPoint
@Around("execution(* com.example.TargetService.*(..))")
public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("环绕通知:方法执行前");
System.out.println("方法参数:" + pjp.getArgs());
try {
Object result = pjp.proceed();
System.out.println("环绕通知:方法执行后");
return result;
} catch (Throwable ex) {
System.out.println("环绕通知:捕获异常");
throw ex;
}
}
// 引介通知:不直接传递参数(示例展示引入接口)
@DeclareParents(
value = "com.example.TargetService+",
defaultImpl = AuditLogImpl.class
)
private AuditLog auditLog;
private static class AuditLogImpl implements AuditLog {
@Override
public void log() {
System.out.println("引介通知:记录审计日志");
}
}
}
// 3. Spring配置类
package com.example;
import org.springframework.context.annotation.*;
@Configuration
@ComponentScan("com.example")
@EnableAspectJAutoProxy
public class AppConfig {
@Bean
public TargetService targetService() {
return new TargetService();
}
}
// 4. 测试类
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(AppConfig.class);
TargetService service = context.getBean(TargetService.class);
// 测试正常流程
service.doTask("参数1");
// 测试无参方法
service.doTaskWithoutParam();
// 测试异常流程
try {
service.doTaskWithError();
} catch (Exception e) {
System.out.println("捕获到异常:" + e.getMessage());
}
// 测试引介接口
AuditLog audit = (AuditLog) service;
audit.log();
}
}
关键点总结表格:
通知类型 | 参数传递方式 | 示例代码片段 | 参数来源说明 |
---|---|---|---|
前置通知 | JoinPoint.getArgs() | Object[] args = joinPoint.getArgs(); | 直接获取方法参数数组 |
后置通知 | JoinPoint + 返回值参数 | public void afterReturningAdvice(JoinPoint joinPoint, Object result) | 返回值通过returning 参数获取 |
异常通知 | JoinPoint + 异常参数 | public void afterThrowingAdvice(JoinPoint joinPoint, Throwable ex) | 异常对象通过throwing 参数获取 |
环绕通知 | ProceedingJoinPoint | pjp.proceed() | 包含完整方法控制权 |
引介通知 | 不直接传递参数(接口绑定) | @DeclareParents | 通过接口实现间接关联 |
执行结果:
前置通知:方法开始
参数值:参数1
环绕通知:方法执行前
方法参数:[参数1]
执行业务逻辑,参数:参数1
环绕通知:方法执行后
后置通知:方法正常返回
返回值:null
参数列表:[参数1]
前置通知:方法开始
环绕通知:方法执行前
方法参数:[]
执行无参业务逻辑
环绕通知:方法执行后
后置通知:方法正常返回
返回值:null
参数列表:[]
前置通知:方法开始
环绕通知:方法执行前
方法参数:[]
执行会抛异常的逻辑
异常通知:方法抛出异常
异常信息:模拟异常
异常发生时的参数:[]
环绕通知:捕获异常
捕获到异常:模拟异常
引介通知:记录审计日志
核心要点:
- JoinPoint:所有通知(除环绕)都通过
JoinPoint
对象获取参数 - ProceedingJoinPoint:环绕通知特有的接口,支持手动执行目标方法
- 参数绑定:通过注解属性(如
returning
/throwing
)声明额外参数 - 参数类型:参数类型需与目标方法参数匹配,可通过
joinPoint.getSignature()
获取方法元数据 - 引介通知:主要用于类型增强,不直接参与参数传递