Spring AOP 面向切面编程
TIP
AOP(Aspect Oriented Programming)通过预编译方式和运行期动态代理实现程序功能的统一维护,将日志、事务等横切关注点与业务逻辑分离。
AOP 核心概念
| 概念 | 说明 |
|---|---|
| Aspect(切面) | 横切关注点的模块化,如日志切面 |
| Join Point(连接点) | 程序执行中的某个点,如方法调用 |
| Pointcut(切点) | 匹配连接点的表达式 |
| Advice(通知) | 在切点上执行的动作 |
| Weaving(织入) | 将切面应用到目标对象的过程 |
通知类型
java
@Aspect
@Component
public class LogAspect {
// 前置通知
@Before("execution(* com.example.service.*.*(..))")
public void before(JoinPoint joinPoint) {
System.out.println("前置通知: " + joinPoint.getSignature().getName());
}
// 后置通知(无论是否异常都执行)
@After("execution(* com.example.service.*.*(..))")
public void after() {
System.out.println("后置通知");
}
// 返回通知(方法正常返回后执行)
@AfterReturning(pointcut = "execution(* com.example.service.*.*(..))", returning = "result")
public void afterReturning(Object result) {
System.out.println("返回通知, 结果: " + result);
}
// 异常通知
@AfterThrowing(pointcut = "execution(* com.example.service.*.*(..))", throwing = "e")
public void afterThrowing(Exception e) {
System.out.println("异常通知: " + e.getMessage());
}
// 环绕通知(功能最强大)
@Around("execution(* com.example.service.*.*(..))")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
long start = System.currentTimeMillis();
Object result = pjp.proceed();
long duration = System.currentTimeMillis() - start;
System.out.println(pjp.getSignature().getName() + " 耗时: " + duration + "ms");
return result;
}
}切点表达式
java
// 匹配指定包下的所有方法
@Pointcut("execution(* com.example.service.*.*(..))")
public void serviceLayer() {}
// 匹配带有 @Log 注解的方法
@Pointcut("@annotation(com.example.annotation.Log)")
public void logAnnotation() {}
// 组合切点
@Around("serviceLayer() && logAnnotation()")
public Object combinedAdvice(ProceedingJoinPoint pjp) throws Throwable {
// ...
}实现原理
Spring AOP 基于动态代理实现:
- JDK 动态代理:目标类实现了接口时使用
- CGLIB 代理:目标类未实现接口时使用
java
// JDK 动态代理示例(简化)
public class JdkProxy implements InvocationHandler {
private Object target;
public Object createProxy(Object target) {
this.target = target;
return Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
this
);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("前置处理");
Object result = method.invoke(target, args);
System.out.println("后置处理");
return result;
}
}TIP
实际开发中常用 AOP 实现日志记录、权限校验、事务管理、性能监控等功能。