DEV Community

Liu yu
Liu yu

Posted on

AOP

AOP学习 + 高频面试题 + 标准答案


🚀 一、Mini-AOP(最小可运行理解版)

核心思想:

AOP = 用动态代理生成一个代理对象
→ 在方法前后加“增强逻辑”
→ 再调用原始对象的方法

我们用 JDK 动态代理写一个最小版本。


🟦 Step 1:定义一个接口(JDK 代理要求接口)

public interface UserService {
    void register();
}
Enter fullscreen mode Exit fullscreen mode

🟦 Step 2:实现类

public class UserServiceImpl implements UserService {
    @Override
    public void register() {
        System.out.println("执行注册业务逻辑");
    }
}
Enter fullscreen mode Exit fullscreen mode

🟦 Step 3:写一个 AOP 代理(核心代码!)

import java.lang.reflect.*;

public class AOPProxy {

    public static Object getProxy(Object target) {

        return Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                new InvocationHandler() {

                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        // ⭐ 方法执行前增强
                        System.out.println("【before】方法执行前:记录日志");

                        Object result = method.invoke(target, args);

                        // ⭐ 方法执行后增强
                        System.out.println("【after】方法执行后:记录日志");

                        return result;
                    }
                }
        );
    }
}
Enter fullscreen mode Exit fullscreen mode

这段小代码就是 Spring AOP 的本质。


🟦 Step 4:测试 mini-AOP

public class Main {
    public static void main(String[] args) {

        UserService target = new UserServiceImpl();

        UserService proxy = (UserService) AOPProxy.getProxy(target);

        proxy.register();
    }
}
Enter fullscreen mode Exit fullscreen mode

输出:

【before】方法执行前:记录日志
执行注册业务逻辑
【after】方法执行后:记录日志
Enter fullscreen mode Exit fullscreen mode

🎉 你现在理解了:

  • Spring AOP = 自动帮你生成这个代理对象
  • 代理对象 = 你的 Bean + 增强逻辑
  • IOC = 负责把“代理对象”注入,而不是“原始对象”

这就是 AOP 的核心!


🧠 二、AOP 高频面试题 + 标准答案(简短但非常专业)


⭐ 1. 什么是 AOP?(必考)

AOP(面向切面编程)是在不修改业务代码的情况下,为方法统一添加横切逻辑(如日志、事务、权限)的机制,通过动态代理在方法执行前后织入增强。


⭐ 2. AOP 的核心概念有哪些?

  • 切面(Aspect):增强逻辑的模块
  • 通知(Advice):前置/后置/环绕逻辑
  • 切点(Pointcut):哪些方法被增强
  • 连接点(JoinPoint):具体的增强位置
  • 织入(Weaving):增强逻辑加入业务逻辑的过程

⭐ 3. Spring AOP 是如何实现的?

基于动态代理:如果类有接口用 JDK Proxy,没有接口使用 CGLIB 生成子类。
容器最终注入的是代理对象而不是原始对象。


⭐ 4. JDK Proxy 和 CGLIB 的区别?

JDK Proxy CGLIB
基于接口 基于继承
必须有接口 不需要接口
性能略慢 性能更好
代理接口 代理类

问得最多的一句:

final 类/方法不能使用 CGLIB,因为无法继承或重写。


⭐ 5. 为什么 @Transactional 有时会失效?

最常见的原因:

  1. 方法不是 public(事务只作用于 public 方法)
  2. 在同一个类里内部调用(没有经过代理对象)
  3. final 方法无法被代理
  4. 类标注 @Transactional 但方法没有 public

最核心一句:

内部调用没有经过代理对象,AOP 不生效。


⭐ 6. @Around 和 @Before/@After 的区别?

  • @Before/@After:只包裹方法前/后,不控制方法执行
  • @Around:完全控制方法执行,可决定是否执行原方法

面试官爱听一句:

@Around 是最强大的通知,因为它能用 ProceedingJoinPoint 控制整个方法链。


⭐ 7. Spring AOP 和 AspectJ 的区别?

  • Spring AOP:运行时,动态代理,功能有限,但足够业务
  • AspectJ:编译时织入,功能强大,多用于框架

面试标准回答:

Spring AOP 是基于代理的“轻量级 AOP”,适合业务增强;
AspectJ 是“完整 AOP 方案”,功能更广,但不常用于普通业务。


⭐ 8. 构造器能否被 AOP 增强?

不能。

原因:

对象构造时代理对象还没创建出来,因此无法增强构造器。


⭐ 9. AOP 为什么依赖 IOC?

因为 AOP 会生成代理对象,如果没有 IOC,业务代码无法自动替换成代理对象,增强就无法生效。


⭐ 10. 你在实际项目中怎么用 AOP?

可以说:

  • 日志记录
  • 统一异常处理
  • 性能监控
  • API 参数校验
  • 权限控制
  • 事务管理(@Transactional)

Top comments (0)