学习材料: AOP Concepts :: Spring Framework
Spring AOP(Aspect-Oriented Programming,面向切面编程)是 Spring 框架中用于实现横切关注点(如日志记录、事务管理、安全性等)的一种编程范式。它通过将这些横切关注点与业务逻辑分离,提高了代码的模块化程度和可维护性。
先看一个切面编程的例子,方便讲解概念,以下是一个简单的 Spring AOP 示例:
@Slf4j
@Aspect
@Component
public class LogAspect {
@Pointcut("execution(* org.derek.ctroller.*.*(..))")
public void log() {
}
@Around("log()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
log.info("LogAspect around start ...");
Object result = joinPoint.proceed();
log.info("LogAspect around end ...");
return result;
}
@Before("log()")
public void before() {
log.info("LogAspect before ...");
}
@AfterReturning(pointcut = "log()", returning = "result")
public void afterReturning(Object result) {
log.info("LogAspect afterReturning ..., result: {}", result);
}
@AfterThrowing(pointcut = "log()", throwing = "exception")
public void afterThrowing(Exception exception) {
log.info("LogAspect afterThrowing ...", exception);
}
@After("log()")
public void after() {
log.info("LogAspect after ...");
}
}
切面是一个模块化的单元,封装了与业务逻辑无关的代码。
在代码中,LogAspect 类就是一个切面,使用了 @Aspect 注解。
@Aspect
@Component
public class LogAspect {
// ...
}
连接点是指程序执行过程中的某个特定点,例如方法调用或异常抛出。
在 Spring AOP 中,连接点通常是方法的执行。
在代码中,execution(* org.derek.ctroller.*.*(..)) 定义了一个连接点,表示匹配 org.derek.ctroller 包及其子包下的所有方法。
通知定义了切面在特定连接点的行为。
Spring AOP 支持以下几种类型的通知:
Before Advice:在方法执行前运行。
After Returning Advice:在方法成功返回后运行。
After Throwing Advice:在方法抛出异常时运行。
After (Finally) Advice:无论方法是否抛出异常,都会运行。
Around Advice:包围方法执行,允许在方法前后进行自定义操作。
在代码中,定义了多种通知:
@Before("log()"):方法执行前的日志记录。
@AfterReturning(pointcut = "log()", returning = "result"):方法返回后的日志记录。
@AfterThrowing(pointcut = "log()", throwing = "exception"):方法抛出异常时的日志记录。
@After("log()"):无论方法是否抛出异常,都会执行的日志记录。
@Around("log()"):包围方法执行的日志记录。
切入点定义了通知应用到哪些连接点。
使用表达式语言来匹配特定的方法签名。
在代码中,@Pointcut("execution(* org.derek.ctroller.*.*(..))") 定义了一个切入点,表示匹配 org.derek.ctroller 包及其子包下的所有方法。
@Pointcut("execution(* org.derek.ctroller.*.*(..))")
public void log() {}
引入允许为现有类添加新的方法或属性。
被一个或多个切面所通知的对象。
Spring AOP 通过动态代理实现 AOP。有两种类型的代理:
JDK 动态代理:适用于实现了接口的目标对象。
CGLIB 代理:适用于没有实现接口的目标对象。
关于代理的内容,可以移步这里有详细讲解:
Proxying Mechanisms :: Spring Framework
织入是将切面应用到目标对象并创建新的代理对象的过程。
织入可以在编译时、类加载时或运行时完成。
总结
Spring AOP 提供了一种灵活的方式来处理横切关注点,而无需修改业务逻辑代码。通过理解上述基本概念,可以更好地设计和实现基于 AOP 的应用程序。LogAspect 类就是一个典型的 Spring AOP 示例,展示了如何通过 AOP 实现日志记录功能。