Spring AOP(面向切面编程,Aspect-Oriented Programming)是 Spring 框架中用于实现横切关注点分离的一种机制。它允许开发者将那些影响多个类的通用功能(如日志记录、事务管理、安全性等)从业务逻辑中分离出来,从而提高代码的模块化和可维护性。
Spring AOP 的核心概念
- 切面(Aspect):包含横切关注点的类。通常通过注解或 XML 配置来定义。
- 连接点(Join Point):程序执行过程中可以插入横切逻辑的点。例如方法调用、异常抛出等。
- 通知(Advice):在特定连接点执行的动作。常见的通知类型有:
-
Before:在方法执行前运行。 -
After Returning:在方法成功返回后运行。 -
After Throwing:在方法抛出异常后运行。 -
After (Finally):无论方法是否抛出异常都会运行。 -
Around:环绕方法执行,在方法调用前后都可以运行自定义逻辑。
- 切入点(Pointcut):定义哪些连接点会被通知拦截。通常使用表达式语言来指定。
- 引入(Introduction):为现有类添加新方法或属性的能力。
示例:日志记录切面
假设我们有一个简单的服务类 UserService,其中包含几个业务方法。我们将创建一个切面来为这些方法添加日志记录功能。
1. 引入依赖
确保你的 pom.xml 或 build.gradle 文件中有 Spring AOP 和 AspectJ 的依赖:
<!-- Maven -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>// Gradle
implementation 'org.springframework.boot:spring-boot-starter-aop'2. 创建服务类
package com.example.demo.service;
import org.springframework.stereotype.Service;
@Service
public class UserService {
public void addUser() {
System.out.println("Adding a new user...");
}
public void updateUser() {
System.out.println("Updating an existing user...");
}
public void deleteUser() {
System.out.println("Deleting a user...");
}
}3. 创建切面类
package com.example.demo.aspect;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class LoggingAspect {
// Before advice: 在目标方法执行之前打印日志
@Before("execution(* com.example.demo.service.UserService.*(..))")
public void logBefore() {
System.out.println("Logging before method execution.");
}
// After returning advice: 在目标方法成功返回之后打印日志
@AfterReturning("execution(* com.example.demo.service.UserService.*(..))")
public void logAfterReturning() {
System.out.println("Logging after method returned successfully.");
}
// After throwing advice: 在目标方法抛出异常之后打印日志
@AfterThrowing(pointcut = "execution(* com.example.demo.service.UserService.*(..))", throwing = "ex")
public void logAfterThrowing(Exception ex) {
System.out.println("Logging after method threw exception: " + ex.getMessage());
}
// Around advice: 环绕目标方法执行,可以在方法调用前后添加逻辑
@Around("execution(* com.example.demo.service.UserService.*(..))")
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("Logging around method execution - before.");
try {
Object result = joinPoint.proceed(); // 执行目标方法
System.out.println("Logging around method execution - after.");
return result;
} catch (Throwable throwable) {
System.out.println("Logging around method execution - exception caught.");
throw throwable;
}
}
}4. 使用服务类
package com.example.demo;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication implements CommandLineRunner {
@Autowired
private UserService userService;
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
userService.addUser();
userService.updateUser();
userService.deleteUser();
}
}运行结果
当你运行这个应用程序时,你会看到类似以下的日志输出:
Logging around method execution - before.
Logging before method execution.
Adding a new user...
Logging around method execution - after.
Logging after method returned successfully.
Logging around method execution - before.
Logging before method execution.
Updating an existing user...
Logging around method execution - after.
Logging after method returned successfully.
Logging around method execution - before.
Logging before method execution.
Deleting a user...
Logging around method execution - after.
Logging after method returned successfully.
















