2007 字
约 6 分钟
1
AOP 到底是什么?一篇文章彻底搞懂:AOP = 动态代理 + 方法拦截 + 增

AOP 到底是什么?一篇文章彻底搞懂:AOP = 动态代理 + 方法拦截 + 增强逻辑

很多 Java 开发者在工作中天天使用 AOP。

比如:

@Transactional
public void saveUser(){

}

或者:

@Log
public void query(){

}

甚至:

@Before
public void checkPermission(){

}

但是很多人只知道:

Spring AOP 很强,可以实现事务、日志、权限控制。

真正问:

Spring AOP 底层为什么可以做到?

很多人就开始模糊。

其实 AOP 的核心并没有那么神秘。

一句话总结:

AOP = 动态代理 + 方法拦截 + 增强逻辑

下面我们拆开来看。


一、为什么需要 AOP?

先看一个业务。

假设我们有一个订单服务:

public class OrderService {


    public void createOrder(){

        System.out.println("创建订单");

    }

}

业务很简单。

但是随着项目发展,我们需要增加:

1. 日志

每次调用记录:

谁调用了
什么时候调用
执行多久

例如:

public void createOrder(){

    System.out.println("开始执行");

    System.out.println("创建订单");

    System.out.println("执行结束");

}

2. 权限校验

例如:

创建订单之前:

if(!user.hasPermission()){

    throw new RuntimeException();

}


3. 事务

例如:

订单创建失败:

需要回滚。


问题来了:

这些代码是不是业务代码?

不是。

创建订单:

属于业务。

日志:

属于系统功能。

权限:

属于系统功能。

事务:

属于系统功能。

如果全部写进去:

public void createOrder(){


    checkPermission();


    beginTransaction();


    log();


    //真正业务

    createOrder();


    commit();


}

最后业务类变成:

业务代码
+
日志代码
+
权限代码
+
事务代码

非常混乱。

所以提出:

AOP

把这些公共功能抽出去。

最终:

业务代码:

public void createOrder(){

    System.out.println("创建订单");

}

但是执行的时候:

自动增加:

权限

 ↓

日志

 ↓

事务

 ↓

业务方法

 ↓

事务提交

 ↓

日志记录

这就是 AOP。


二、AOP 的核心思想:代理

那么问题来了:

你没有修改:

OrderService

为什么执行的时候多出了东西?

答案:

代理对象

假设原对象:

OrderService

Spring 创建一个代理:

OrderServiceProxy

以后调用:

orderService.createOrder();

实际上:

调用的是:

OrderServiceProxy.createOrder()

代理里面:

public void createOrder(){


    checkPermission();


    log();


    target.createOrder();


    saveLog();


}

所以:

AOP 本质就是:

用代理对象包裹真实对象,在调用真实方法之前和之后执行额外逻辑。


三、什么是动态代理?

代理有两种:

1. 静态代理

自己写代理类。

例如:

目标:

public class UserService{


    public void save(){

        System.out.println("保存用户");

    }

}

代理:

public class UserServiceProxy{


    private UserService target;


    public void save(){


        System.out.println("日志开始");


        target.save();


        System.out.println("日志结束");


    }


}

问题:

如果有100个类:

你写100个代理。

太麻烦。


2. 动态代理

动态代理:

不用自己写代理类。

程序运行的时候自动生成。

例如:

UserService

        |
        |
        ↓

动态生成

        |
        |
        ↓


UserServiceProxy

Java提供:

JDK动态代理

要求:

必须实现接口。

例如:

public interface UserService{


    void save();


}


CGLIB动态代理

不需要接口。

直接继承。

例如:

原类:

public class UserService{


    public void save(){

    }

}

CGLIB生成:

public class UserServiceProxy
extends UserService{


}

Spring现在默认更倾向使用 CGLIB。


四、方法拦截:AOP真正执行的位置

代理生成了。

但是:

怎么知道什么时候执行增强逻辑?

答案:

方法拦截

例如 CGLIB:

public Object intercept(
        Object obj,
        Method method,
        Object[] args,
        MethodProxy proxy
)

所有方法调用都会进入:

intercept()

例如:

调用:

userService.save();

实际上:

Proxy.save()

        |
        |
        ↓

intercept()

        |
        |
        ↓

执行增强逻辑

        |
        |
        ↓

调用真实save()


五、增强逻辑是什么?

增强逻辑就是:

你想额外增加的代码。

比如:

Before

方法执行前:

@Before
public void before(){

    System.out.println("检查权限");

}

流程:

before

 ↓

目标方法


After

方法执行后:

@After
public void after(){

    System.out.println("记录日志");

}

流程:

目标方法

 ↓

after


Around

环绕通知。

最强。

例如:

@Around
public Object around(
        ProceedingJoinPoint point
)
throws Throwable{


    System.out.println("开始");


    Object result =
        point.invoke();


    System.out.println("结束");


    return result;


}

执行:

开始

 ↓

目标方法

 ↓

结束

甚至:

point.invoke();

不执行。

那么:

目标方法不会执行。


六、把三个东西组合起来

现在:

AOP =

① 动态代理

负责:

创建代理对象。

例如:

UserService

      ↓

UserServiceProxy


② 方法拦截

负责:

拦截方法调用。

例如:

save()

 ↓

intercept()


③ 增强逻辑

负责:

添加额外功能。

例如:

before

after

around

组合:

调用方法


    ↓


代理对象


    ↓


方法拦截


    ↓


执行增强逻辑


    ↓


目标方法


这就是完整 AOP。


七、手写一个简单 AOP

我们模拟 Spring。

目标类:

public class UserService {


    public void save(){

        System.out.println("保存用户");

    }

}


定义增强:

public class LogAspect {


    public void before(){

        System.out.println("方法开始");

    }


    public void after(){

        System.out.println("方法结束");

    }

}


创建代理:

Enhancer enhancer =
        new Enhancer();


enhancer.setSuperclass(
        UserService.class
);


enhancer.setCallback(
        new MethodInterceptor(){

            public Object intercept(
                    Object obj,
                    Method method,
                    Object[] args,
                    MethodProxy proxy
            )
            throws Throwable{


                System.out.println("before");


                Object result =
                    proxy.invokeSuper(
                        obj,
                        args
                    );


                System.out.println("after");


                return result;

            }

        }
);


UserService proxy =
        (UserService)
        enhancer.create();


调用:

proxy.save();

输出:

before

保存用户

after

是不是和 Spring AOP 一模一样?

只是 Spring 帮你自动完成:

  • 找切面
  • 找切点
  • 创建代理
  • 织入增强

八、Spring AOP 为什么使用 BeanPostProcessor?

因为 Spring 创建 Bean 有生命周期:

创建对象


 ↓


初始化


 ↓


放入IOC容器

其中:

BeanPostProcessor 可以插入:

初始化前

初始化后

例如:

public Object postProcessAfterInitialization(
        Object bean
){

    return proxy;

}

原来:

UserService对象

替换:

UserService代理对象

所以:

@Autowired 注入的其实不是原对象。

而是:

代理对象。


九、多个 AOP 怎么办?

例如:

一个方法:

@Auth
@Transactional
@Log
public void save(){

}

三个增强:

权限

日志

事务

怎么办?

答案:

AOP链

类似:

责任链模式。

结构:

Proxy


 |
 |
权限Interceptor


 |
 |
日志Interceptor


 |
 |
事务Interceptor


 |
 |
target


执行:

权限before

日志before

事务开启


业务方法


事务提交

日志after

权限after

这也是 Spring AOP 底层思想。


十、面试总结

如果面试官问:

"你理解 AOP 吗?"

可以回答:

AOP 的核心思想是通过代理对象对目标对象进行增强,本质是动态代理、方法拦截以及增强逻辑的组合。Spring AOP 在 Bean 生命周期中通过 BeanPostProcessor 判断目标对象是否匹配切点,如果匹配则创建代理对象。调用代理方法时进入拦截器链,在目标方法执行前后织入 Before、After、Around 等增强逻辑。多个切面通过责任链模式组成 interceptor chain 顺序执行。


最后一句话记忆

不要背 Spring AOP。

记住这个模型:

业务对象

      ↓

动态代理包装


      ↓

拦截方法调用


      ↓

执行增强逻辑


      ↓

调用真实方法


所以:

AOP不是魔法,它就是一个会自动生成的代理对象,在调用方法的时候偷偷插入一些代码。

理解这一句话,Spring AOP 的大门就打开了。

AOP 到底是什么?一篇文章彻底搞懂:AOP = 动态代理 + 方法拦截 + 增
http://clxhxhhr.top/posts/381/
作者
clxstart
发布于
2026-09-01
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。