Spring的AOP:从使用到源码原理进行全解析

Spring的AOP:从使用到源码原理进行全解析

前言

​ 在软件开发中,我们经常遇到这样的场景:需要在多个模块中记录日志、处理事务、检查权限。这些功能虽然与核心业务无关,却散布在代码的各个角落,造成大量重复代码。面向切面编程(AOP)正是为了解决这个问题而生。

​ Spring AOP作为Spring框架的核心模块之一,它通过动态代理技术,让我们能够将那些横切关注点(cross-cutting concerns)与业务逻辑分离,实现高内聚、低解耦的代码结构。

​ 本文将带你从使用方式出发,逐步深入到源码层面,全面解析Spring AOP的实现原理。我们会详细分析Spring如何创建代理对象、如何匹配增强器、如何执行拦截器链,并结合源码片段流程图,让你真正理解Spring AOP的每一个环节。

第一部分:AOP实战入门

1.1 从一个痛点开始

想象一下,你正在开发一个电商系统,需要在每个业务方法执行时记录日志、监控性能、检查权限。最直接的方式是在每个方法中编写重复代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class OrderService {
public Order createOrder(Long userId, Long productId) {
// 日志记录
log.info("创建订单开始,参数:userId={}, productId={}", userId, productId);
// 权限检查
checkPermission(userId);
long start = System.currentTimeMillis();

try {
// 核心业务逻辑
Order order = doCreateOrder(userId, productId);

// 性能监控
long cost = System.currentTimeMillis() - start;
log.info("创建订单完成,耗时:{}ms", cost);
return order;
} catch (Exception e) {
log.error("创建订单异常", e);
throw e;
}
}
}

如果几十个业务类都这样写,代码重复率高达60%以上,维护成本极高。AOP的出现,就是为了解决这个问题。

1.2 Spring AOP快速上手

1.2.1 环境配置

在Spring Boot项目中,只需引入一个starter:

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>

无需额外配置,Spring Boot会自动启用AOP功能。

1.2.2 核心注解详解

Spring AOP提供了五个核心注解,对应五种通知类型

注解 通知类型 执行时机
@Before 前置通知 目标方法执行前
@After 后置通知 目标方法执行后(无论是否异常)
@AfterReturning 返回通知 目标方法正常返回后
@AfterThrowing 异常通知 目标方法抛出异常后
@Around 环绕通知 包围目标方法,可控制执行时机

1.2.3 完整示例:日志切面

让我们通过一个完整的日志切面,快速掌握AOP的使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
@Component
@Aspect
public class LogAspect {

// 定义切点:匹配service包下所有类的所有方法
@Pointcut("execution(* com.example.service.*.*(..))")
public void serviceMethods() {}

// 前置通知
@Before("serviceMethods()")
public void logBefore(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
Object[] args = joinPoint.getArgs();
System.out.printf("[前置通知] 方法:%s,参数:%s%n",
methodName, Arrays.toString(args));
}

// 后置通知
@After("serviceMethods()")
public void logAfter(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
System.out.printf("[后置通知] 方法:%s 执行完毕%n", methodName);
}

// 返回通知
@AfterReturning(pointcut = "serviceMethods()", returning = "result")
public void logAfterReturning(JoinPoint joinPoint, Object result) {
String methodName = joinPoint.getSignature().getName();
System.out.printf("[返回通知] 方法:%s,返回值:%s%n", methodName, result);
}

// 异常通知
@AfterThrowing(pointcut = "serviceMethods()", throwing = "ex")
public void logAfterThrowing(JoinPoint joinPoint, Exception ex) {
String methodName = joinPoint.getSignature().getName();
System.out.printf("[异常通知] 方法:%s,异常:%s%n", methodName, ex.getMessage());
}

// 环绕通知
@Around("serviceMethods()")
public Object logAround(ProceedingJoinPoint pjp) throws Throwable {
long start = System.currentTimeMillis();

try {
// 执行目标方法
Object result = pjp.proceed();
long cost = System.currentTimeMillis() - start;
System.out.printf("[环绕通知] 方法:%s,耗时:%dms%n",
pjp.getSignature().getName(), cost);
return result;
} catch (Exception e) {
System.out.printf("[环绕通知] 方法:%s 异常:%s%n",
pjp.getSignature().getName(), e.getMessage());
throw e;
}
}
}

1.2.4 切点表达式详解

切点表达式是AOP的核心,它决定了哪些方法会被拦截。常用的表达式类型如下:

1. execution:方法执行切点(最常用)

1
2
3
4
5
6
7
8
// 匹配指定包下所有类的所有方法
@Pointcut("execution(* com.example.service.*.*(..))")

// 匹配指定类的所有public方法
@Pointcut("execution(public * com.example.service.UserService.*(..))")

// 匹配特定方法(指定参数类型)
@Pointcut("execution(* com.example.service.OrderService.createOrder(Long, String))")

2. within:类型匹配

1
2
3
4
5
// 匹配指定包下的所有类
@Pointcut("within(com.example.service.*)")

// 匹配指定类
@Pointcut("within(com.example.service.UserService)")

3. @annotation:注解匹配

1
2
// 匹配标注了@Transactional注解的方法
@Pointcut("@annotation(org.springframework.transaction.annotation.Transactional)")

4. args:参数匹配

1
2
// 匹配第一个参数为Long类型的方法
@Pointcut("args(Long,..)")

1.2.5 ProceedingJoinPoint的妙用

在环绕通知中,ProceedingJoinPoint是核心对象,它提供了控制目标方法执行的能力:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Around("@annotation(cacheable)")
public Object cache(ProceedingJoinPoint pjp, Cacheable cacheable) throws Throwable {
String key = generateKey(pjp.getArgs());
Object value = redisTemplate.opsForValue().get(key);

if (value != null) {
return value; // 缓存命中,直接返回,不执行目标方法
}

// 执行目标方法
Object result = pjp.proceed();

// 存入缓存
redisTemplate.opsForValue().set(key, result, cacheable.ttl(), TimeUnit.SECONDS);
return result;
}

1.3 实战案例:权限控制切面

来看一个电商系统中典型的权限控制切面:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
@Component
@Aspect
public class PermissionAspect {

@Autowired
private HttpServletRequest request;

@Autowired
private PermissionService permissionService;

@Around("@annotation(permission)")
public Object checkPermission(ProceedingJoinPoint pjp, Permission permission)
throws Throwable {

// 获取当前用户
String token = request.getHeader("Authorization");
Long userId = JwtUtils.getUserId(token);

// 检查权限
String[] requiredPermissions = permission.value();
boolean hasPermission = permissionService.checkPermissions(userId, requiredPermissions);

if (!hasPermission) {
throw new BusinessException("无权限访问");
}

// 权限通过,执行业务方法
return pjp.proceed();
}
}

// 自定义权限注解
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Permission {
String[] value(); // 所需权限列表
}

// 使用方式
@RestController
public class OrderController {

@PostMapping("/order/delete")
@Permission({"order:delete", "admin"})
public Result deleteOrder(@RequestParam Long orderId) {
// 业务逻辑
return Result.success();
}
}

第二部分:AOP核心概念与理论基础

2.1 AOP核心术语解析

在深入源码之前,我们需要彻底理解AOP的几个核心概念:

术语 含义 代码中的体现
切面(Aspect) 封装横切关注点的模块 @Aspect注解的类
连接点(Joinpoint) 程序执行过程中的可插入点 主要是方法调用
切点(Pointcut) 定义哪些连接点会被拦截 @Pointcut表达式
通知(Advice) 切面在特定连接点执行的操作 @Before等方法
目标对象(Target) 被切面拦截的原始对象 业务类实例
代理对象(Proxy) 为目标对象创建的代理实例 JDK/CGLIB代理对象
织入(Weaving) 将切面应用到目标对象的过程 创建代理对象的过程

2.2 代理模式:AOP的基石

Spring AOP的本质是代理模式的应用。让我们先从静态代理入手,理解代理模式的核心思想。

2.2.1 静态代理:简单直观但不够灵活

以房屋交易为例,中介代理业主完成房屋交易:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
// 抽象主题:定义业务接口
public interface HouseSubject {
void saleHouse(); // 房屋出售
void rentHouse(); // 房屋租赁
}

// 真实主题:业主执行具体业务
public class RealHouseSubject implements HouseSubject {
@Override
public void saleHouse() {
System.out.println("业主执行房屋出售流程:签订合同 → 办理过户");
}
@Override
public void rentHouse() {
System.out.println("业主执行房屋租赁流程:签订租约 → 交付房屋");
}
}

// 代理类:中介增强业务
public class HouseProxy implements HouseSubject {
private HouseSubject realSubject;

public HouseProxy(HouseSubject realSubject) {
this.realSubject = realSubject;
}

@Override
public void saleHouse() {
// 前置增强
System.out.println("[中介] 审核房屋产权证明 → 评估市场价格");

// 调用真实业务
realSubject.saleHouse();

// 后置增强
System.out.println("[中介] 协助办理水电过户 → 交易归档");
}

@Override
public void rentHouse() {
// 前置增强
System.out.println("[中介] 核实租客身份 → 签订租赁担保协议");

// 调用真实业务
realSubject.rentHouse();

// 后置增强
System.out.println("[中介] 每月房屋状况巡检");
}
}

静态代理的优缺点

  • 优点:简单直观,易于理解
  • 缺点
    • 增强逻辑硬编码在代理类中
    • 每个业务类都需要一个代理类,导致类爆炸
    • 业务方法增减时,代理类必须同步修改

2.2.2 JDK动态代理:基于接口的代理

JDK动态代理是Java原生支持的代理机制,它要求目标类必须实现至少一个接口

核心组件:

  • Proxy类:动态生成代理类
  • InvocationHandler接口:定义增强逻辑
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
public class JdkDynamicProxyExample {

// 目标接口
interface UserService {
void addUser(String name);
}

// 目标类
static class UserServiceImpl implements UserService {
@Override
public void addUser(String name) {
System.out.println("添加用户:" + name);
}
}

// InvocationHandler实现
static class LogInvocationHandler implements InvocationHandler {
private final Object target;

public LogInvocationHandler(Object target) {
this.target = target;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 前置增强
System.out.println("[JDK代理] 方法执行前:" + method.getName());

// 调用目标方法
Object result = method.invoke(target, args);

// 后置增强
System.out.println("[JDK代理] 方法执行后:" + method.getName());

return result;
}
}

public static void main(String[] args) {
// 创建目标对象
UserService target = new UserServiceImpl();

// 创建代理对象
UserService proxy = (UserService) Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new LogInvocationHandler(target)
);

// 通过代理调用方法
proxy.addUser("张三");
}
}

JDK动态代理的核心流程

  1. Proxy.newProxyInstance()动态生成代理类字节码
  2. 代理类实现目标接口,所有方法调用转发给InvocationHandler
  3. InvocationHandler.invoke()执行增强逻辑,通过反射调用目标方法

2.2.3 CGLIB动态代理:基于继承的代理

CGLIB(Code Generation Library)通过继承目标类来创建代理,适合没有接口的类。

核心组件:

  • Enhancer类:生成代理类
  • MethodInterceptor接口:定义增强逻辑
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public class CglibProxyExample {

// 目标类(无接口)
static class OrderService {
public void createOrder(String product) {
System.out.println("创建订单:" + product);
}
}

// MethodInterceptor实现
static class LogMethodInterceptor implements MethodInterceptor {

@Override
public Object intercept(Object obj, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
// 前置增强
System.out.println("[CGLIB代理] 方法执行前:" + method.getName());

// 调用目标方法(通过MethodProxy调用父类方法)
Object result = proxy.invokeSuper(obj, args);

// 后置增强
System.out.println("[CGLIB代理] 方法执行后:" + method.getName());

return result;
}
}

public static void main(String[] args) {
// 创建Enhancer
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(OrderService.class);
enhancer.setCallback(new LogMethodInterceptor());

// 创建代理对象
OrderService proxy = (OrderService) enhancer.create();

// 通过代理调用方法
proxy.createOrder("iPhone");
}
}

CGLIB代理的核心流程

  1. Enhancer设置父类为目标类
  2. 动态生成目标类的子类,重写所有非final方法
  3. 方法调用转发给MethodInterceptor.intercept()
  4. intercept()中通过MethodProxy.invokeSuper()调用父类方法

2.2.4 两种代理方式对比

对比维度 JDK动态代理 CGLIB代理
原理 基于接口,实现相同接口 基于继承,生成子类
对目标类的要求 必须实现接口 无接口限制
性能 创建代理较快,调用稍慢 创建代理较慢,调用较快
限制 只能代理接口方法 不能代理final方法和final类
Spring Boot 2.x默认 仅当目标类没有接口时使用 默认开启,优先使用

2.3 Spring AOP与AspectJ的关系

Spring AOP和AspectJ是两个经常被混淆的概念:

  • Spring AOP:基于动态代理的运行时织入,是Spring框架的一部分,只能代理方法级别的拦截
  • AspectJ:完整的AOP框架,支持编译时、编译后、加载时织入,可以拦截字段访问、构造方法等更细粒度的连接点

Spring AOP借用了AspectJ的注解风格(如@Aspect@Before等),但底层实现仍是基于动态代理。

第三部分:源码深度解析 - 代理对象的创建

理解了理论基础后,我们进入源码分析环节。Spring AOP的核心流程可以分为三大步:

  1. 触发机制:在Bean初始化后判断是否需要创建代理
  2. 匹配增强器:查找适用于当前Bean的切面
  3. 创建代理对象:选择JDK或CGLIB生成代理

我们以Spring Boot自动配置方式为例,基于Spring 5.3.x源码进行分析。

3.1 触发机制:从后处理器开始

Spring AOP的入口是一个BeanPostProcessor——AnnotationAwareAspectJAutoProxyCreator。它会在Bean初始化完成后,检查是否需要为该Bean创建代理。

3.1.1 如何启用AOP

在纯Spring项目中,我们需要通过@EnableAspectJAutoProxy注解或XML配置<aop:aspectj-autoproxy/>来显式开启AOP功能。

1
2
3
4
5
@Configuration
@EnableAspectJAutoProxy // 开启Spring AOP,使用AspectJ注解
public class JiangAppConfig {
// 其他Bean定义
}

@EnableAspectJAutoProxy注解的源码如下:

1
2
3
4
5
6
7
8
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class) // 核心:导入注册器
public @interface EnableAspectJAutoProxy {
boolean proxyTargetClass() default false;
boolean exposeProxy() default false;
}

3.1.2 AspectJAutoProxyRegistrar注册后处理器

AspectJAutoProxyRegistrar实现了ImportBeanDefinitionRegistrar接口,负责向容器中注册AOP后处理器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
BeanDefinitionRegistry registry) {
// 注册 AnnotationAwareAspectJAutoProxyCreator
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

// 获取 @EnableAspectJAutoProxy 注解属性
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata,
EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy != null) {
// 设置 proxyTargetClass 属性
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
// 设置 exposeProxy 属性
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
}

​ 最终注册到容器中的是AnnotationAwareAspectJAutoProxyCreator,它继承自AbstractAutoProxyCreator,而后者实现了BeanPostProcessor接口。因此,Spring容器在启动时会将这个后处理器实例化,并在每个Bean初始化后自动调用其postProcessAfterInitialization方法。

3.1.3 AbstractAutoProxyCreator的核心方法

AbstractAutoProxyCreator作为骨架类,定义了代理创建的核心流程。其关键字段如下:

字段 类型 作用
earlyProxyReferences Map<Object, Object> 存储早期代理引用,Key为Bean的缓存键(通常是BeanName或Bean实例的标识),Value为原始Bean。用于解决循环依赖:当Bean正在创建且被提前暴露时,记录该引用,避免重复创建代理。
targetSourcedBeans Set<String> 记录已经通过自定义TargetSource创建了代理的Bean名称。如果Bean已经通过TargetSource代理,则后续不再处理。
advisedBeans Map<Object, Boolean> 缓存Bean是否需要被代理的结果。Key为Bean的缓存键,Value为BooleanTRUE表示需要代理,FALSE表示不需要。用于避免重复判断,提升性能。
proxyTypes Map<Object, Class<?>> 缓存代理对象的类型,Key为Bean的缓存键,Value为代理对象的Class。用于快速获取代理类型。
proxyClassLoader ClassLoader 代理类的类加载器,默认为beanClassLoader

使用时机

  • earlyProxyReferencesgetEarlyBeanReference方法中填充,用于提前暴露代理以解决循环依赖。
  • advisedBeanswrapIfNecessary中查询和设置,避免重复解析切面。
  • targetSourcedBeanscreateProxy后添加,标记已通过自定义TargetSource创建代理。

关键方法是postProcessAfterInitialization,它在Bean初始化后被调用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// AbstractAutoProxyCreator.java
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
// 获取缓存键
Object cacheKey = getCacheKey(bean.getClass(), beanName);
// 如果当前bean不在早期代理引用集合中,说明需要处理
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
// 核心方法:如果需要则包装bean为代理
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}

wrapIfNecessary方法是整个AOP代理创建的入口:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// AbstractAutoProxyCreator.java
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
// 如果已经存在目标源(表示已经处理过),直接返回原始bean
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}

// 如果缓存中标记为不需要代理,直接返回原始bean
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}

// 检查是否是基础设施类(如切面类自身)或应该跳过
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}

// 核心:获取适用于当前bean的通知/增强器
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(
bean.getClass(), beanName, null);

// 如果存在适用的增强器,则创建代理
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// 创建代理对象
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors,
new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}

// 没有适用的增强器,标记为不需要代理
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}

3.2 匹配增强器:查找适用的切面

获取适用增强器的方法是getAdvicesAndAdvisorsForBean,它在AbstractAdvisorAutoProxyCreator中实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// AbstractAdvisorAutoProxyCreator.java
@Override
@Nullable
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {

// 查找所有可用的Advisor
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
// 1. 查找所有候选Advisor
List<Advisor> candidateAdvisors = findCandidateAdvisors();

// 2. 筛选出可应用于当前bean的Advisor
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(
candidateAdvisors, beanClass, beanName);

// 3. 扩展Advisors(钩子方法,子类可扩展)
extendAdvisors(eligibleAdvisors);

// 4. 排序
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}

return eligibleAdvisors;
}

3.2.1 查找候选Advisor

findCandidateAdvisorsAnnotationAwareAspectJAutoProxyCreator中被重写,目标是为了获取到所有的Advisors

Advisor是Spring AOP中最基本的接口,它包含一个Advice(增强逻辑)。常见的实现类有InstantiationModelAwarePointcutAdvisorImpl(用于AspectJ注解方式)和DefaultPointcutAdvisor(编程式使用)。

InstantiationModelAwarePointcutAdvisorImpl 字段:

字段 类型 作用
pointcut Pointcut 切点定义,用于匹配连接点。
advice Advice 真正的增强逻辑,可能是MethodBeforeAdviceAspectJAfterAdvice等。
aspectName String 所属切面Bean的名称。
declarationOrder int 在切面类中的声明顺序,用于排序。
isBeforeAdvice boolean 缓存是否为前置通知。
isAfterAdvice boolean 缓存是否为后置通知。
isLazy boolean 标记是否懒加载切面实例。

DefaultPointcutAdvisor 字段:

字段 类型 作用
pointcut Pointcut 切点,默认为TruePointcut.INSTANCE(匹配所有方法)。
advice Advice 增强逻辑。
order int 排序顺序,可通过setOrder设置。

该方法会扫描所有@Aspect注解的类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// AnnotationAwareAspectJAutoProxyCreator.java
@Override
protected List<Advisor> findCandidateAdvisors() {
List<Advisor> advisors = super.findCandidateAdvisors();

// 解析所有@Aspect注解的类,生成Advisor
if (this.aspectJAdvisorsBuilder != null) {
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}

return advisors;
}

// ReflectiveAspectJAdvisorFactory.java 中的解析逻辑
public List<Advisor> buildAspectJAdvisors() {
// 获取所有beanName
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
beanFactory, Object.class, true, false);

for (String beanName : beanNames) {
Class<?> beanType = beanFactory.getType(beanName);
if (beanType == null) continue;

// 检查是否标注了@Aspect注解
if (this.advisorFactory.isAspect(beanType)) {
// 解析切面类中的方法,为每个通知方法创建Advisor
List<Advisor> classAdvisors =
this.advisorFactory.getAdvisors(getAspectInstanceFactory(beanName));
// 缓存结果
advisors.addAll(classAdvisors);
}
}
return advisors;
}

一个@Aspect类如何被解析成多个Advisor

1
2
3
4
5
6
7
8
9
10
11
12
13
@Aspect
@Component
public class LogAspect {

@Before("execution(* com..*.*(..))")
public void before() { ... }

@After("execution(* com..*.*(..))")
public void after() { ... }

@Around("execution(* com..*.*(..))")
public Object around() { ... }
}

以上切面类会被解析成3个Advisor,每个Advisor包含:

  • Pointcut:从表达式解析而来
  • Advice:封装了通知方法的信息
  • 优先级:根据@Order注解或方法名排序

3.2.2 筛选可应用的Advisor

findAdvisorsThatCanApply方法负责筛选出能应用于当前Bean的Advisor:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
// AbstractAdvisorAutoProxyCreator.java
protected List<Advisor> findAdvisorsThatCanApply(
List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {

// 标记当前正在代理的beanName(用于处理循环引用)
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
// 调用AopUtils的工具方法筛选
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
} finally {
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}

// AopUtils.java
public static List<Advisor> findAdvisorsThatCanApply(
List<Advisor> advisors, Class<?> clazz) {

if (advisors.isEmpty()) {
return advisors;
}

List<Advisor> eligibleAdvisors = new ArrayList<>();
for (Advisor advisor : advisors) {
// 判断Advisor是否能应用到目标类
if (canApply(advisor, clazz)) {
eligibleAdvisors.add(advisor);
}
}
return eligibleAdvisors;
}

public static boolean canApply(Advisor advisor, Class<?> targetClass) {
if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pca = (PointcutAdvisor) advisor;
// 核心:判断切点是否匹配目标类
return canApply(pca.getPointcut(), targetClass);
}
// 非PointcutAdvisor(如IntroductionAdvisor)直接返回true
return true;
}

public static boolean canApply(Pointcut pc, Class<?> targetClass) {
// 1. 类过滤器先匹配
if (!pc.getClassFilter().matches(targetClass)) {
return false;
}

// 2. 查找目标类中所有方法
Method[] methods = ReflectionUtils.getAllDeclaredMethods(targetClass);
for (Method method : methods) {
// 3. 方法匹配器匹配
if (pc.getMethodMatcher().matches(method, targetClass)) {
return true;
}
}
return false;
}

这里的核心逻辑是:判断切点表达式是否能匹配目标类的任何一个方法。只要有一个方法匹配,这个Advisor就适用于当前Bean。

3.2.3 Advisor的排序

多个Advisor的执行顺序很重要,Spring通过sortAdvisors方法进行排序:

1
2
3
4
5
6
7
8
9
10
11
// AbstractAdvisorAutoProxyCreator.java
protected List<Advisor> sortAdvisors(List<Advisor> advisors) {
// 使用AnnotationAwareOrderComparator排序
AnnotationAwareOrderComparator.sort(advisors);
return advisors;
}

// AnnotationAwareOrderComparator会考虑:
// 1. @Order注解的值(值越小优先级越高)
// 2. Ordered接口的getOrder()方法
// 3. @Priority注解

排序规则总结

  • 优先级数值越小的越先执行
  • 相同优先级的,执行顺序由切面类中通知方法的定义顺序决定
  • @Around > @Before > @After > @AfterReturning/@AfterThrowing(在同一个切面内)

3.3 创建代理对象

当确定了需要代理的Bean和适用的Advisor后,createProxy方法负责实际创建代理对象:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// AbstractAutoProxyCreator.java
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {

// 创建代理工厂
ProxyFactory proxyFactory = new ProxyFactory();

// 复制当前配置(如proxyTargetClass、exposeProxy等)
proxyFactory.copyFrom(this);

// 如果不是代理接口(由proxyTargetClass控制)
if (!proxyFactory.isProxyTargetClass()) {
// 评估是否需要使用CGLIB代理
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
} else {
// 根据接口情况设置
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}

// 构建增强器数组
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);

// 设置目标源
proxyFactory.setTargetSource(targetSource);

// 空方法,留给子类扩展
customizeProxyFactory(proxyFactory);

// 控制代理工厂是否允许冻结配置(冻结后不能修改Advisor)
proxyFactory.setFrozen(this.freezeProxy);

if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}

// 获取代理对象
return proxyFactory.getProxy(getProxyClassLoader());
}

3.3.1 ProxyFactory的核心配置

ProxyFactory是创建代理的核心类,它继承自ProxyCreatorSupport,后者又继承自AdvisedSupportAdvisedSupport包含了创建代理所需的所有配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// AdvisedSupport.java
public class AdvisedSupport extends ProxyConfig implements Advised {

private TargetSource targetSource; // 目标源
private List<Advisor> advisors = new ArrayList<>(); // 增强器列表
private Class<?>[] interfaces; // 要代理的接口

// ... 配置方法
}

// ProxyConfig.java(父类)
public class ProxyConfig implements Serializable {
private boolean proxyTargetClass = false; // 是否使用CGLIB
private boolean optimize = false; // 是否启用优化
private boolean opaque = false; // 是否可强制转换为Advised
private boolean exposeProxy = false; // 是否暴露代理到ThreadLocal
private boolean frozen = false; // 是否冻结配置
}

3.3.2 代理方式的选择策略

getProxy方法最终调用createAopProxy创建代理:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
// ProxyCreatorSupport.java
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
// 委托给AopProxyFactory
return getAopProxyFactory().createAopProxy(this);
}

// DefaultAopProxyFactory.java(默认实现)
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {

@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
// 选择代理策略:是否使用CGLIB?
if (config.isOptimize() || config.isProxyTargetClass() ||
hasNoUserSuppliedProxyInterfaces(config)) {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("...");
}
// 目标类是接口 或 本身就是JDK代理类 → 使用JDK动态代理
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
// 否则使用CGLIB代理
return new ObjenesisCglibAopProxy(config);
} else {
// 默认使用JDK动态代理
return new JdkDynamicAopProxy(config);
}
}

/**
* 判断是否没有用户提供的代理接口
* 两种情况:
* 1. 接口数组为空
* 2. 只有一个接口,且是SpringProxy(标记接口)
*/
private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
Class<?>[] ifcs = config.getProxiedInterfaces();
return (ifcs.length == 0 ||
(ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0])));
}
}

3.3.3 JdkDynamicAopProxy源码分析

JdkDynamicAopProxy实现了InvocationHandlerAopProxy接口:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
// JdkDynamicAopProxy.java
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {

private final AdvisedSupport advised;

public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
this.advised = config;
}

@Override
public Object getProxy() {
return getProxy(ClassUtils.getDefaultClassLoader());
}

@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
// 获取要代理的接口
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);

// JDK动态代理创建代理对象
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}

@Override
@Nullable
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;

TargetSource targetSource = this.advised.targetSource;
Object target = null;

try {
// 处理equals/hashCode方法(不进行代理)
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
return equals(args[0]);
}
if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
return hashCode();
}

// 处理装饰类方法
if (method.getDeclaringClass() == DecoratingProxy.class) {
return AopProxyUtils.ultimateTargetClass(this.advised);
}

// 如果方法来自接口且无需代理
if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}

Object retVal;

// 判断是否暴露代理到ThreadLocal
if (this.advised.exposeProxy) {
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}

// 获取目标对象
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);

// 获取拦截器链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(
method, targetClass);

// 如果没有拦截器,直接反射调用目标方法
if (chain.isEmpty()) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
} else {
// 创建方法调用对象,执行拦截器链
MethodInvocation invocation = new ReflectiveMethodInvocation(
proxy, target, method, args, targetClass, chain);
retVal = invocation.proceed();
}

// 处理返回值类型(如返回this的场景)
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target &&
returnType != Object.class && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
retVal = proxy;
}
return retVal;

} finally {
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
if (setProxyContext) {
AopContext.setCurrentProxy(oldProxy);
}
}
}
}

3.3.4 CglibAopProxy源码分析

CglibAopProxy使用CGLIB的Enhancer创建代理:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
// CglibAopProxy.java
class CglibAopProxy implements AopProxy, Serializable {

private final AdvisedSupport advised;

@Override
public Object getProxy() {
return getProxy(null);
}

@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
Class<?> rootClass = this.advised.getTargetClass();

// 创建Enhancer
Enhancer enhancer = new Enhancer();
if (classLoader != null) {
enhancer.setClassLoader(classLoader);
}

// 设置要代理的接口
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
enhancer.setInterfaces(proxiedInterfaces);

// 设置父类(目标类)
enhancer.setSuperclass(rootClass);
enhancer.setInterceptDuringConstruction(false);

// 设置命名策略
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);

// 设置生成策略
enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));

// 设置回调
Callback[] callbacks = getCallbacks(rootClass);
enhancer.setCallbacks(callbacks);
enhancer.setCallbackFilter(new ProxyCallbackFilter(this.advised));

// 生成代理对象
return createProxyClassAndInstance(enhancer, callbacks);
}

/**
* 核心拦截器 - DynamicAdvisedInterceptor
*/
private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {

private final AdvisedSupport advised;

@Override
@Nullable
public Object intercept(Object proxy, Method method, Object[] args,
MethodProxy methodProxy) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
Object target = null;
TargetSource targetSource = this.advised.getTargetSource();

try {
// 是否暴露代理
if (this.advised.exposeProxy) {
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}

target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);

// 获取拦截器链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(
method, targetClass);

Object retVal;
// 如果拦截器链为空,直接调用目标方法
if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
// 使用MethodProxy直接调用(性能更好)
retVal = methodProxy.invoke(target, args);
} else {
// 创建方法调用对象
MethodInvocation invocation = new CglibMethodInvocation(
proxy, target, method, args, targetClass, chain, methodProxy);
retVal = invocation.proceed();
}

// 处理返回值类型
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target &&
returnType != Object.class && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
retVal = proxy;
}
return retVal;

} finally {
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
if (setProxyContext) {
AopContext.setCurrentProxy(oldProxy);
}
}
}
}
}

第四部分:源码深度解析 - 代理的执行

代理对象创建完成后,当调用代理对象的方法时,拦截器链如何执行?这是AOP的核心执行机制。

4.1 拦截器链的获取

invoke方法中,通过getInterceptorsAndDynamicInterceptionAdvice获取拦截器链:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
// AdvisedSupport.java
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Method method, @Nullable Class<?> targetClass) {

// 创建缓存键
MethodCacheKey cacheKey = new MethodCacheKey(method);
// 从缓存中获取
List<Object> cached = this.methodCache.get(cacheKey);
if (cached == null) {
// 通过AdvisorAdapterRegistry将Advisor转换为MethodInterceptor
cached = this.advisorAdapterRegistry.getInterceptorsAndDynamicInterceptionAdvice(
this, method, targetClass);
this.methodCache.put(cacheKey, cached);
}
return cached;
}

// DefaultAdvisorAdapterRegistry.java
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, @Nullable Class<?> targetClass) {

List<Object> interceptorList = new ArrayList<>(config.getAdvisors().length);
Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());

// 遍历所有Advisor
for (Advisor advisor : config.getAdvisors()) {
if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
// 检查切点是否匹配当前方法
if (pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass) &&
pointcutAdvisor.getPointcut().getMethodMatcher().matches(method, actualClass)) {
// 从Advisor中获取Advice,并适配为MethodInterceptor
MethodInterceptor[] interceptors =
registry.getInterceptors(advisor);
for (MethodInterceptor interceptor : interceptors) {
interceptorList.add(interceptor);
}
}
} else if (advisor instanceof IntroductionAdvisor) {
// 引介增强的特殊处理
if (config.isPreFiltered() ||
((IntroductionAdvisor) advisor).getClassFilter().matches(actualClass)) {
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
} else {
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
return interceptorList;
}

关键点AdvisorAdapterRegistry负责将不同类型的Advice适配为MethodInterceptor

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// DefaultAdvisorAdapterRegistry.java
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
List<MethodInterceptor> interceptors = new ArrayList<>(3);
Advice advice = advisor.getAdvice();

// 如果已经是MethodInterceptor,直接添加
if (advice instanceof MethodInterceptor) {
interceptors.add((MethodInterceptor) advice);
}

// 通过适配器转换
for (AdvisorAdapter adapter : this.adapters) {
if (adapter.supportsAdvice(advice)) {
interceptors.add(adapter.getInterceptor(advisor));
}
}

if (interceptors.isEmpty()) {
throw new UnknownAdviceTypeException(advisor.getAdvice());
}
return interceptors.toArray(new MethodInterceptor[0]);
}

pring内置了三个适配器,分别对应@Before@AfterReturning@AfterThrowing(注意@Around本身就是MethodInterceptor):

  • MethodBeforeAdviceAdapter:将MethodBeforeAdvice适配为MethodInterceptor
  • AfterReturningAdviceAdapter:将AfterReturningAdvice适配为MethodInterceptor
  • ThrowsAdviceAdapter:将ThrowsAdvice适配为MethodInterceptor

4.2 ReflectiveMethodInvocation的proceed方法

当有了拦截器链后,ReflectiveMethodInvocation负责按顺序执行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
// ReflectiveMethodInvocation.java
public class ReflectiveMethodInvocation implements ProxyMethodInvocation, Cloneable {

protected final Object proxy; // 代理对象
protected final Object target; // 目标对象
protected final Method method; // 目标方法
protected Object[] arguments; // 方法参数
private final Class<?> targetClass; // 目标类
private List<Object> interceptorsAndDynamicMethodMatchers; // 拦截器链
private int currentInterceptorIndex = -1; // 当前执行索引

@Override
@Nullable
public Object proceed() throws Throwable {
// 执行完所有拦截器后,调用目标方法
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}

// 获取下一个拦截器
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);

// 如果是动态方法匹配器,需要动态匹配
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;

// 动态匹配:参数也会影响匹配结果
if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
} else {
// 不匹配,跳过,继续下一个
return proceed();
}
} else {
// 普通MethodInterceptor,直接执行
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}

@Nullable
protected Object invokeJoinpoint() throws Throwable {
// 反射调用目标方法
return AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments);
}
}

核心机制:这是一个递归+索引的执行模式。

  • currentInterceptorIndex从-1开始
  • 每次proceed()将索引+1,获取下一个拦截器
  • 拦截器内部调用invocation.proceed()继续执行下一个
  • 最后一个拦截器执行完后,调用目标方法

4.3 拦截器执行流程剖析

让我们通过一个具体例子,理解拦截器链的执行流程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 切面定义
@Aspect
public class LogAspect {
@Before("execution(* *.*(..))")
public void before() { System.out.println("before"); }

@After("execution(* *.*(..))")
public void after() { System.out.println("after"); }

@Around("execution(* *.*(..))")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("around start");
Object result = pjp.proceed();
System.out.println("around end");
return result;
}
}

当调用代理对象的方法时,拦截器链的执行顺序如下:

执行顺序

关键点说明

  1. @Around包裹了整个执行过程,可以控制proceed()的调用
  2. @Before在目标方法前执行
  3. @After通过try-finally机制保证在目标方法后执行
  4. 多个拦截器通过递归链式调用

4.4 不同类型通知的拦截器实现

4.4.1 AspectJAroundAdvice(环绕通知)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// AspectJAroundAdvice.java
public class AspectJAroundAdvice extends AbstractAspectJAdvice
implements MethodInterceptor {

@Override
public Object invoke(MethodInvocation mi) throws Throwable {
// 检查是否应该提前调用
if (!(mi instanceof ProxyMethodInvocation)) {
throw new IllegalStateException("...");
}

ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
// 创建MethodInvocationProceedingJoinPoint
ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
try {
// 调用切面方法
return invokeAdviceMethod(pjp, null, null);
} catch (Throwable t) {
throw t;
}
}
}

4.4.2 MethodBeforeAdviceInterceptor(前置通知)

1
2
3
4
5
6
7
8
9
10
11
12
13
// MethodBeforeAdviceInterceptor.java
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {

private final MethodBeforeAdvice advice;

@Override
public Object invoke(MethodInvocation mi) throws Throwable {
// 执行前置通知
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
// 继续执行拦截器链
return mi.proceed();
}
}

4.4.3 AfterReturningAdviceInterceptor(返回通知)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// AfterReturningAdviceInterceptor.java
public class AfterReturningAdviceInterceptor implements MethodInterceptor, AfterAdvice, Serializable {

private final AfterReturningAdvice advice;

@Override
public Object invoke(MethodInvocation mi) throws Throwable {
// 先执行后续拦截器
Object retVal = mi.proceed();
// 再执行返回通知
this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
return retVal;
}
}

4.4.5 AspectJAfterThrowingAdvice(异常通知)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// AspectJAfterThrowingAdvice.java
public class AspectJAfterThrowingAdvice extends AbstractAspectJAdvice
implements MethodInterceptor, AfterAdvice {

@Override
public Object invoke(MethodInvocation mi) throws Throwable {
try {
return mi.proceed();
} catch (Throwable t) {
// 发生异常时执行异常通知
if (shouldInvokeOnThrowing(t)) {
invokeAdviceMethod(getJoinPointMatch(), null, t);
}
throw t;
}
}
}

4.5 拦截器执行顺序总结

综合上述源码分析,我们可以得出拦截器的执行顺序:

1
2
3
4
5
6
7
8
9
10
11
12
13
try {
// 1. @Around 前置逻辑
// 2. @Before
// 3. 目标方法执行
// 4. @AfterReturning(正常返回)
return result;
} catch (Exception e) {
// 5. @AfterThrowing(异常返回)
throw e;
} finally {
// 6. @After(总是执行)
}
// 7. @Around 后置逻辑

多个切面的执行顺序

  • 切面优先级:@Order(1) < @Order(2)(值越小优先级越高)
  • 同一优先级:按切面类名排序(不可控)
  • 同一切面内:@Around@Before@After@AfterReturning/@AfterThrowing

第五部分:常见问题

5.1 同一个类内部方法调用的问题

这是一个经典的AOP陷阱:同一个类中的方法调用不会触发AOP增强。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Service
public class UserService {

@Transactional
public void methodA() {
// 事务生效
System.out.println("methodA");
}

public void methodB() {
// 直接调用methodA,事务不生效!
this.methodA();
}
}

原因分析

  • Spring AOP基于代理,外部调用通过代理对象进入
  • this.methodA()调用的是目标对象本身,不是代理对象
  • 代理逻辑无法被触发

解决方案

  1. 重构代码(推荐)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Service
public class UserService {

@Transactional
public void methodA() { ... }
}

@Service
public class AnotherService {
@Autowired
private UserService userService; // 注入代理对象

public void methodB() {
userService.methodA(); // 通过代理调用
}
}
  1. 自我注入(需要Spring 5+)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Service
public class UserService {

@Autowired
@Lazy
private UserService self; // 注入自身代理

@Transactional
public void methodA() { ... }

public void methodB() {
self.methodA(); // 通过代理调用
}
}
  1. 使用AopContext获取当前代理
1
2
3
4
5
6
7
8
9
10
11
@Service
public class UserService {

@Transactional
public void methodA() { ... }

public void methodB() {
// 需要配置 exposeProxy = true
((UserService) AopContext.currentProxy()).methodA();
}
}

5.2 代理方式的选择策略

Spring Boot 2.x开始,默认使用CGLIB代理。可以通过配置调整:

1
2
3
spring:
aop:
proxy-target-class: false # 改为JDK动态代理

选择建议

  • JDK动态代理:目标类有完善的接口设计,追求更清晰的抽象
  • CGLIB代理:无接口的类,或需要代理所有方法(包括非接口方法)

结语

通过本文的源码分析,我们完整地走通了Spring AOP的创建执行两大核心流程:

代理创建流程

  1. @EnableAspectJAutoProxy注册AnnotationAwareAspectJAutoProxyCreator
  2. postProcessAfterInitialization触发代理创建
  3. wrapIfNecessary判断是否需要代理
  4. getAdvicesAndAdvisorsForBean查找匹配的增强器
  5. createProxy根据配置选择JDK或CGLIB生成代理

代理执行流程

  1. 代理对象方法调用进入invoke/intercept
  2. 获取匹配当前方法的拦截器链
  3. ReflectiveMethodInvocation递归执行拦截器
  4. 各种Advice按顺序执行其增强逻辑
  5. 最终调用目标方法并返回结果

理解这些原理,不仅能帮助我们更好地使用AOP,还能在遇到问题时快速定位并解决。希望本文能对你深入理解Spring AOP有所帮助。


Spring的AOP:从使用到源码原理进行全解析
https://johnjoyjzw.github.io/2024/09/18/Spring的AOP:从使用到源码原理进行全解析/
Author
JiangZW
Posted on
September 18, 2024
Licensed under