代号转生成为魔塔
52.35M · 2026-04-02
mindmap
root((AOP 核心术语))
切面 Aspect
切点 Pointcut
通知 Advice
连接点 JoinPoint
方法执行
字段访问
目标对象 Target
被代理的对象
代理对象 Proxy
增强后的对象
织入 Weaving
编译期
类加载期
运行期
| 术语 | 英文 | 说明 | 示例 |
|---|---|---|---|
| 切面 | Aspect | 横切关注点的模块化 | @Aspect 注解的类 |
| 连接点 | JoinPoint | 程序执行的某个位置 | 方法执行、异常抛出 |
| 切点 | Pointcut | 匹配连接点的表达式 | @Pointcut("execution(_ com.._.*(..))") |
| 通知 | Advice | 切面在特定连接点执行的动作 | @Before、@After、@Around |
| 目标对象 | Target | 被代理的对象 | UserService |
| 代理对象 | Proxy | 增强后的对象 | $Proxy、UserService$$EnhancerBySpringCGLIB |
| 织入 | Weaving | 将切面应用到目标对象的过程 | Spring AOP 在运行时织入 |
@Aspect
@Component
public class LoggingAspect {
// 1. 前置通知:方法执行前
@Before("execution(* com.example.service.*.*(..))")
public void beforeAdvice(JoinPoint joinPoint) {
System.out.println("前置通知:" + joinPoint.getSignature().getName());
}
// 2. 后置通知:方法执行后(无论成功或异常)
@After("execution(* com.example.service.*.*(..))")
public void afterAdvice(JoinPoint joinPoint) {
System.out.println("后置通知:" + joinPoint.getSignature().getName());
}
// 3. 返回通知:方法成功返回后
@AfterReturning(pointcut = "execution(* com.example.service.*.*(..))",
returning = "result")
public void afterReturningAdvice(JoinPoint joinPoint, Object result) {
System.out.println("返回通知:" + joinPoint.getSignature().getName() + ", 结果:" + result);
}
// 4. 异常通知:方法抛出异常后
@AfterThrowing(pointcut = "execution(* com.example.service.*.*(..))",
throwing = "ex")
public void afterThrowingAdvice(JoinPoint joinPoint, Exception ex) {
System.out.println("异常通知:" + joinPoint.getSignature().getName() + ", 异常:" + ex.getMessage());
}
// 5. 环绕通知:包围方法执行(最强大)
@Around("execution(* com.example.service.*.*(..))")
public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("环绕通知 - 前");
Object result = joinPoint.proceed(); // 执行目标方法
System.out.println("环绕通知 - 后");
return result;
}
}
| 通知类型 | 注解 | 执行时机 | 能否修改参数 | 能否修改返回值 | 能否阻止执行 |
|---|---|---|---|---|---|
| 前置通知 | @Before | 方法执行前 | |||
| 后置通知 | @After | 方法执行后 | |||
| 返回通知 | @AfterReturning | 方法成功返回后 | |||
| 异常通知 | @AfterThrowing | 方法抛出异常后 | |||
| 环绕通知 | @Around | 包围方法 |
// 1. 定义接口
public interface UserService {
void save();
void delete();
}
// 2. 目标类(实现接口)
@Service
public class UserServiceImpl implements UserService {
@Override
public void save() {
System.out.println("保存用户");
}
@Override
public void delete() {
System.out.println("删除用户");
}
}
// 3. JDK 动态代理实现
public class JDKProxyTest {
public static void main(String[] args) {
UserService target = new UserServiceImpl();
// 创建代理对象
UserService proxy = (UserService) 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("前置增强");
Object result = method.invoke(target, args); // 调用目标方法
System.out.println("后置增强");
return result;
}
}
);
proxy.save(); // 调用代理对象的方法
}
}
输出:
前置增强
保存用户
后置增强
// java.lang.reflect.Proxy
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h) {
// 1. 检查参数
Objects.requireNonNull(h);
// 2. 获取代理类(可能从缓存获取)
Class<?> cl = getProxyClass0(loader, intfs);
// 3. 获取代理类的构造器(参数为 InvocationHandler)
final Constructor<?> cons = cl.getConstructor(constructorParams);
// 4. 创建代理对象实例
return cons.newInstance(new Object[]{h});
}
// 生成的代理类(简化版)
public final class $Proxy0 extends Proxy implements UserService {
private static Method m1;
private static Method m2;
private static Method m3;
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
m3 = Class.forName("com.example.UserService").getMethod("save");
} catch (NoSuchMethodException var2) { }
}
public $Proxy0(InvocationHandler var1) {
super(var1);
}
public final void save() {
try {
super.h.invoke(this, m3, null); // 调用 InvocationHandler
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
}
关键点:
$Proxy0 继承 Proxy,实现 UserService 接口InvocationHandler#invoke()method.invoke(target, args)sequenceDiagram
participant Client
participant Proxy as 代理对象($Proxy0)
participant IH as InvocationHandler
participant Target as 目标对象
Client->>Proxy: proxy.save()
Proxy->>IH: invoke(proxy, method, args)
IH->>IH: 前置增强
IH->>Target: method.invoke(target, args)
Target-->>IH: 返回结果
IH->>IH: 后置增强
IH-->>Proxy: 返回结果
Proxy-->>Client: 返回结果
// 1. 目标类(无需实现接口)
@Service
public class OrderService {
public void create() {
System.out.println("创建订单");
}
public void cancel() {
System.out.println("取消订单");
}
}
// 2. CGLIB 代理实现
public class CGLIBProxyTest {
public static void main(String[] args) {
OrderService target = new OrderService();
// 创建代理对象
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass()); // 设置父类
enhancer.setCallback(new MethodInterceptor() { // 设置回调
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("前置增强");
Object result = proxy.invokeSuper(obj, args); // 调用父类方法
System.out.println("后置增强");
return result;
}
});
OrderService proxy = (OrderService) enhancer.create();
proxy.create(); // 调用代理对象的方法
}
}
输出:
前置增强
创建订单
后置增强
flowchart TD
A[Enhancer 创建代理] --> B[生成目标类的子类]
B --> C[重写父类的非 final 方法]
C --> D[设置 MethodInterceptor 回调]
D --> E[调用代理方法]
E --> F{方法是否被拦截?}
F -->|是| G[执行 MethodInterceptor.intercept]
F -->|否| H[直接调用父类方法]
G --> I[前置增强]
I --> J[proxy.invokeSuper 调用父类]
J --> K[后置增强]
K --> L[返回结果]
| 特性 | JDK 动态代理 | CGLIB 动态代理 |
|---|---|---|
| 代理类名 | $Proxy0、$Proxy1 | OrderService$$EnhancerBySpringCGLIB$$12345 |
| 继承关系 | 继承 Proxy,实现接口 | 继承目标类 |
| 方法调用 | InvocationHandler#invoke() | MethodInterceptor#intercept() |
| 目标方法调用 | method.invoke(target, args) | proxy.invokeSuper(obj, args) |
| 类加载器 | 目标类类加载器 | 自定义 ClassLoader |
flowchart LR
A[目标类是否实现接口] -->|是| B{强制使用 CGLIB?}
A -->|否| C[使用 CGLIB]
B -->|是| C
B -->|否| D[使用 JDK 动态代理]
| 对比维度 | JDK 动态代理 | CGLIB 动态代理 |
|---|---|---|
| 实现原理 | 反射机制 | 字节码生成(ASM) |
| 代理类继承 | 继承 Proxy,实现接口 | 继承目标类 |
| JDK 支持 | 原生支持 | 需要引入 CGLIB 依赖 |
| final 类、方法 | 不影响 | 无法代理 |
| Spring 优先选择 | 优先选择 | 降级方案 |
| 性能 | 创建快,执行稍慢 | 创建慢,执行快 |
// DefaultAopProxyFactory#createProxy()
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
// 如果配置了强制使用 CGLIB或者目标对象没有实现任何接口
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
// 使用 CGLIB 动态代理
return new CglibAopProxy(config);
} else {
// 其他情况都使用 JDK 动态代理
return new JdkDynamicAopProxy(config);
}
}
选择策略:
@EnableAspectJAutoProxy(proxyTargetClass = true)flowchart TD
A["@Aspect 注解类"] --> B[AspectJParser]
B --> C[Advisor 通知器]
C --> D[PointcutAdvisor]
C --> E[IntroductionAdvisor]
D --> F[Pointcut 切点]
D --> G[Advice 通知]
F --> H[Pointcut Expression]
G --> I[MethodBeforeAdvice]
G --> J[AfterReturningAdvice]
G --> K[AfterThrowingAdvice]
G --> L[AroundAdvice]
| 组件 | 说明 | 示例 |
|---|---|---|
| Advisor | 通知器,包含 Pointcut 和 Advice | AspectJExpressionPointcutAdvisor |
| Pointcut | 切点,匹配连接点 | execution(* com.example.service.*.*(..)) |
| Advice | 通知,在切点执行的动作 | MethodBeforeAdvice、AroundAdvice |
| JoinPoint | 连接点,程序执行的位置 | 方法执行、异常抛出 |
// AbstractAutoProxyCreator#createProxy()
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
// 1. 获取 Advisors(通知器)
Object[] advisors = buildAdvisors(beanName, specificInterceptors);
// 2. 创建代理工厂
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this.advised);
// 3. 判断使用 JDK 还是 CGLIB
if (!proxyFactory.isProxyTargetClass()) {
if (shouldUseCGLIB(proxyFactory)) { // 判断是否使用 CGLIB
proxyFactory.setProxyTargetClass(true);
}
}
// 4. 创建代理对象
return proxyFactory.getProxy(getProxyClassLoader());
}
sequenceDiagram
participant Client
participant Proxy as 代理对象
participant AdvisorChain as AdvisorChain
participant Advisor1 as Advisor1
participant Advisor2 as Advisor2
participant Target as 目标对象
Client->>Proxy: proxy.method()
Proxy->>AdvisorChain: 获取 AdvisorChain
loop 每个 Advisor
AdvisorChain->>Advisor1: 执行前置通知
AdvisorChain->>Advisor2: 执行前置通知
end
AdvisorChain->>Target: 调用目标方法
Target-->>AdvisorChain: 返回结果
loop 每个 Advisor(倒序)
AdvisorChain->>Advisor2: 执行后置通知
AdvisorChain->>Advisor1: 执行后置通知
end
AdvisorChain-->>Proxy: 返回结果
Proxy-->>Client: 返回结果
@Aspect
@Component
public class TransactionAspect {
@Pointcut("execution(* com.example.service.*.*(..))")
public void serviceLayer() {}
@Before("serviceLayer()")
public void beforeAdvice(JoinPoint joinPoint) {
System.out.println("前置通知");
}
@Around("serviceLayer()")
public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("环绕通知 - 前");
Object result = joinPoint.proceed();
System.out.println("环绕通知 - 后");
return result;
}
}
// AspectJAutoProxyBeanPostProcessor#postProcessBeforeInitialization
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
// 1. 扫描 @Aspect 注解的类
if (bean.getClass().isAnnotationPresent(Aspect.class)) {
// 2. 解析 @Pointcut、@Before、@After 等注解
parseAspectAnnotations(bean);
}
return bean;
}
private void parseAspectAnnotations(Object aspectBean) {
Class<?> aspectClass = aspectBean.getClass();
// 1. 解析 @Pointcut
for (Method method : aspectClass.getDeclaredMethods()) {
if (method.isAnnotationPresent(Pointcut.class)) {
Pointcut pointcut = method.getAnnotation(Pointcut.class);
// 保存切点表达式
registerPointcut(pointcut.value(), method);
}
}
// 2. 解析 @Before、@After、@Around
for (Method method : aspectClass.getDeclaredMethods()) {
if (method.isAnnotationPresent(Before.class)) {
Before before = method.getAnnotation(Before.class);
// 创建 Advisor:Pointcut + Advice
Advisor advisor = createAdvisor(before.value(), method, aspectBean);
registerAdvisor(advisor);
}
}
}
| @Aspect 注解 | Advice 类型 | Advisor 类型 | 执行时机 |
|---|---|---|---|
| @Before | MethodBeforeAdvice | AspectJMethodBeforeAdvice | 方法执行前 |
| @After | AfterAdvice | AspectJAfterAdvice | 方法执行后(finally) |
| @AfterReturning | AfterReturningAdvice | AspectJAfterReturningAdvice | 方法成功返回后 |
| @AfterThrowing | ThrowsAdvice | AspectJAfterThrowingAdvice | 方法抛出异常后 |
| @Around | MethodInterceptor | AspectJAroundAdvice | 包围方法执行 |
问题代码:
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
@Transactional
public void methodA() {
methodB(); // 自调用,@Transactional 失效
}
@Transactional
public void methodB() {
userRepository.save();
}
}
原因分析:
flowchart TD
A[外部调用 userService.methodA] --> B[代理对象拦截]
B --> C[执行 @Transactional 前置逻辑]
C --> D[调用目标对象 methodA]
D --> E[methodA 内部调用 methodB]
E --> F[直接调用 this.methodB]
F --> G[" 绕过代理,@Transactional 失效"]
解决方案:
// 方案1:自己注入自己(推荐)⭐⭐⭐⭐⭐
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
@Autowired
private UserService self; // Spring 会注入代理对象
@Transactional
public void methodA() {
self.methodB(); // 通过代理对象调用
}
@Transactional
public void methodB() {
userRepository.save();
}
}
// 方案2:使用 AopContext.currentProxy()
@Service
public class UserService {
@Transactional
public void methodA() {
((UserService) AopContext.currentProxy()).methodB(); // 通过代理对象调用
}
}
// 方案3:拆分到另一个 Service
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
@Autowired
private UserLogService userLogService;
@Transactional
public void methodA() {
userLogService.log(); // 调用其他 Service 的代理对象
}
}
@Service
public class UserLogService {
@Transactional
public void log() {
// 日志逻辑
}
}
// 方案4:编程式事务
问题代码:
@Service
public class UserService {
@Transactional
private void methodB() { // private 方法无法代理
userRepository.save();
}
}
原因:private 方法无法被代理类重写(JDK)或继承(CGLIB)
解决方案:将方法改为 public 或 protected
问题代码:
@Service
public class UserService {
@Transactional
public final void methodB() { // final 方法无法被 CGLIB 重写
userRepository.save();
}
}
原因:final 方法无法被 CGLIB 子类重写
解决方案:去掉 final 修饰符
// JDK 动态代理
java.lang.reflect.Proxy
java.lang.reflect.InvocationHandler
// CGLIB 动态代理
org.springframework.cglib.proxy.Enhancer
org.springframework.cglib.proxy.MethodInterceptor
org.springframework.cglib.proxy.MethodProxy
// Spring AOP 核心类
org.springframework.aop.framework.ProxyFactory
org.springframework.aop.framework.JdkDynamicAopProxy
org.springframework.aop.framework.CglibAopProxy
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator
org.springframework.aop.framework.DefaultAopProxyFactory
// @Aspect 注解解析
org.springframework.aop.aspectj.annotation.AspectJProxyFactory
org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator