一、Spring Execution概述
Spring Execution是Spring框架提供的一个用于执行方法的工具,它提供了丰富的AOP功能。Spring框架的AOP模块通过代理技术实现,将方法调用转化为对代理对象的调用,并在代理对象的方法中进行前置、后置、异常和返回通知等操作,从而实现对目标方法的增强。Spring Execution正是在这个过程中扮演了重要的角色,是实现AOP的关键之一。
二、Spring Execution常用注解
@Pointcut
在Spring Execution中,@Pointcut用于定义切点,表示哪些方法需要被增强。@Pointcut注解的值是一个String类型,表示一个切点表达式,用于匹配目标方法。以下是一个示例:
@Pointcut("execution(* com.example.demo.service..*.*(..))")
public void servicePointcut() {}
上述示例中,切点表达式匹配com.example.demo.service包中的所有方法,包括其子包中的所有方法。
@Before
@Before用于在目标方法执行前执行增强操作。示例如下:
@Before("servicePointcut()")
public void beforeAdvice(JoinPoint joinPoint) {
System.out.println("Before advice for " + joinPoint.getSignature().getName());
}
上述示例中,beforeAdvice方法在servicePointcut匹配的方法执行前被执行,输出目标方法的名称。
@AfterReturning
@AfterReturning用于在目标方法正常返回后执行增强操作。以下是一个示例:
@AfterReturning(pointcut = "servicePointcut()", returning = "result")
public void afterReturningAdvice(JoinPoint joinPoint, Object result) {
System.out.println("After returning advice for " + joinPoint.getSignature().getName() + ", result=" + result);
}
上述示例中,afterReturningAdvice方法在servicePointcut匹配的方法正常返回后被执行,输出目标方法的名称和返回值。
@AfterThrowing
@AfterThrowing用于在目标方法抛出异常后执行增强操作。以下是一个示例:
@AfterThrowing(pointcut = "servicePointcut()", throwing = "ex")
public void afterThrowingAdvice(JoinPoint joinPoint, Exception ex) {
System.out.println("After throwing advice for " + joinPoint.getSignature().getName() + ", exception=" + ex.getMessage());
}
上述示例中,afterThrowingAdvice方法在servicePointcut匹配的方法抛出异常后被执行,输出目标方法的名称和异常信息。
@After
@After用于在目标方法执行完成后执行增强操作,无论目标方法是正常返回还是抛出异常。以下是一个示例:
@After("servicePointcut()")
public void afterAdvice(JoinPoint joinPoint) {
System.out.println("After advice for " + joinPoint.getSignature().getName());
}
上述示例中,afterAdvice方法在servicePointcut匹配的方法执行完成后被执行,输出目标方法的名称。
三、Spring Execution使用示例
以下是一个简单的示例,演示如何使用Spring Execution进行增强:
@Service
public class SampleService {
public void sampleMethod(String param) throws Exception {
System.out.println("Executing sampleMethod with param " + param);
if (param == null) {
throw new Exception("param cannot be null");
}
}
}
@Aspect
@Component
public class SampleAspect {
@Pointcut("execution(* com.example.demo.service.SampleService.sampleMethod(..)) && args(param)")
public void samplePointcut(String param) {}
@Before("samplePointcut(param)")
public void beforeAdvice(String param) {
System.out.println("Before advice for sampleMethod with param " + param);
}
@AfterThrowing(pointcut = "samplePointcut(param)", throwing = "ex")
public void afterThrowingAdvice(String param, Exception ex) {
System.out.println("After throwing advice for sampleMethod with param " + param + ", exception=" + ex.getMessage());
}
}
@RestController
public class SampleController {
@Autowired
private SampleService sampleService;
@GetMapping("/sample")
public String sampleMethod(@RequestParam(required = false) String param) throws Exception {
sampleService.sampleMethod(param);
return "success";
}
}
上述示例中,定义了一个SampleService类,其中包含一个sampleMethod方法,该方法接收一个参数,并可能抛出异常。通过定义SampleAspect类,使用@Before和@AfterThrowing注解分别增强了sampleMethod方法的前置和异常通知。在SampleController中,通过@Autowired注入了SampleService,并在/sample接口中调用了sampleMethod方法。如果/sample接口中未传递param参数,则会触发异常,导致执行afterThrowingAdvice方法。