Spring AOP注解实现详解

360影视 动漫周边 2025-05-28 17:10 2

摘要:Spring AOP 的注解实现提供了声明式的切面编程能力,结合自定义注解可轻松实现日志记录、性能监控、事务管理等横切关注点,大幅提升代码复用性和可维护性。

Spring AOP 注解实现详解

Spring AOP 通过注解提供了简洁的面向切面编程实现方式。以下是完整实现步骤:

1. 添加 Maven 依赖

org.springframework

spring-context

5.3.23

org.springframework

spring-aop

5.3.23

org.aspectj

aspectjweaver

1.9.9.1

2. 创建目标服务类

java

@Service

public class UserService {

public void createUser(String username) {

System.out.println("创建用户: " + username);

}

public void deleteUser(String username) {

System.out.println("删除用户: " + username);

}

}

3. 创建切面类(核心实现)

java

@Aspect

@Component

public class LoggingAspect {

// 定义切入点(匹配所有Service层方法)

@Pointcut("execution(* com.example.service.*.*(..))")

public void serviceLayer {}

// 前置通知

@Before("serviceLayer")

public void logBefore(JoinPoint joinPoint) {

String methodName = joinPoint.getSignature.getName;

System.out.println("[前置通知] 方法执行: " + methodName);

}

// 返回后通知

@AfterReturning(pointcut = "serviceLayer", returning = "result")

public void logAfterReturning(JoinPoint joinPoint, Object result) {

System.out.println("[返回通知] 方法返回: " + result);

}

// 环绕通知(可控制方法执行)

@Around("serviceLayer")

public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {

long start = System.currentTimeMillis;

Object result = joinPoint.proceed; // 执行目标方法

long time = System.currentTimeMillis - start;

System.out.println("[环绕通知] 执行耗时: " + time + "ms");

return result;

}

// 异常通知

@AfterThrowing(pointcut = "serviceLayer", throwing = "ex")

public void logException(JoinPoint joinPoint, Exception ex) {

System.err.println("[异常通知] 方法异常: " + ex.getMessage);

}

// 最终通知(类似finally)

@After("serviceLayer")

public void logAfter(JoinPoint joinPoint) {

System.out.println("[最终通知] 方法结束");

}

}

4. 配置类启用AOP

java

@Configuration

@ComponentScan(basePackages = "com.example")

@EnableAspectJAutoProxy // 关键注解:启用AOP代理

public class AppConfig {

}

5. 测试类

java

public class AopTest {

public static void main(String args) {

ApplicationContext context =

new AnnotationConfigApplicationContext(AppConfig.class);

UserService userService = context.getBean(UserService.class);

userService.createUser("张三");

userService.deleteUser("李四");

}

}

执行结果示例

[前置通知] 方法执行: createUser

[环绕通知] 执行开始...

创建用户: 张三

[返回通知] 方法返回: null

[最终通知] 方法结束

[环绕通知] 执行耗时: 12ms

[前置通知] 方法执行: deleteUser

[环绕通知] 执行开始...

删除用户: 李四

[返回通知] 方法返回: null

[最终通知] 方法结束

[环绕通知] 执行耗时: 5ms

核心注解说明

注解作用@Aspect声明当前类为切面类@Pointcut定义可重用的切入点表达式@Before前置通知(方法执行前触发)@AfterReturning返回通知(方法正常返回后触发)@Around环绕通知(包裹目标方法执行)@AfterThrowing异常通知(方法抛出异常时触发)@After最终通知(类似finally块)@EnableAspectJAutoProxy启用AspectJ自动代理

高级用法示例

自定义注解实现切面

java

// 1. 定义自定义注解

@Target(ElementType.METHOD)

@Retention(RetentionPolicy.RUNTIME)

public @interface AuditLog {

String action;

}

// 2. 在切面中使用注解切入点

@Aspect

@Component

public class AuditAspect {

@Around("@annotation(auditLog)")

public Object audit(ProceedingJoinPoint pjp, AuditLog auditLog) throws Throwable {

System.out.println("审计动作: " + auditLog.action);

return pjp.proceed;

}

}

// 3. 在服务方法上使用

@Service

public class PaymentService {

@AuditLog(action = "支付操作")

public void processPayment {

System.out.println("处理支付...");

}

}

执行顺序控制

java

@Aspect

@Component

@Order(1) // 数字越小优先级越高

public class FirstAspect {

@Before("execution(* com.example.service.*.*(..))")

public void firstAdvice {

System.out.println("第一个切面");

}

}

@Aspect

@Component

@Order(2)

public class SecondAspect {

@Before("execution(* com.example.service.*.*(..))")

public void secondAdvice {

System.out.println("第二个切面");

}

}

常见问题解决

切面不生效检查清单

Ø 切面类需有 @Component@Aspect

Ø 包扫描路径包含切面类和目标类

Ø 目标方法必须是public(Spring AOP限制)

Ø 目标方法需通过Spring代理调用(直接调用内部方法不生效)

获取方法参数

java

@Before("serviceLayer")

public void logParams(JoinPoint joinPoint) {

Object args = joinPoint.getArgs;

// 处理参数...

修改返回值(环绕通知)

java

@Around("serviceLayer")

public Object modifyResult(ProceedingJoinPoint pjp) throws Throwable {

Object result = pjp.proceed;

if(result instanceof String) {

return ((String) result).toUpperCase;

}

return result;

}

Spring AOP 的注解实现提供了声明式的切面编程能力,结合自定义注解可轻松实现日志记录、性能监控、事务管理等横切关注点,大幅提升代码复用性和可维护性。

来源:老客数据一点号

相关推荐