代理专栏总结
该专栏围绕 Java 代理、Spring AOP 及 @Transactional 注解展开,系统梳理了相关概念、原理及应用场景,以下是核心知识点总结:
一、Java 代理机制
1. 静态代理
- 定义:代理类与目标类实现相同接口,代理类持有目标类实例,通过代理类间接调用目标方法。
- 核心特点: - 代理类在方法执行前后可添加额外逻辑(如性能监控、日志记录)。
- 适用于需要对目标类功能进行扩展的场景。
- 需手动编写代理类,灵活性较低。
 
2. 动态代理
- 定义:在程序运行时动态生成代理类,无需提前编译,通过反射机制实现功能扩展。
- 核心思想:解耦业务逻辑与增强逻辑,不修改目标对象代码。
- 分类及实现: - JDK 动态代理: - 基于接口实现,代理类必须实现目标接口。
- 通过Proxy.newProxyInstance生成代理类,步骤包括参数检查、字节码生成、类加载。
 
- CGLIB 动态代理: - 基于类继承实现,无需接口,适用于代理普通类。
- 通过字节码生成技术创建子类作为代理类。
 
- ByteBuddy: - 无需实现固定接口(如InvocationHandler),通过注解自动匹配拦截逻辑。
- 参数包括代理对象(@This)、被拦截方法(@Origin)、方法参数(@AllArguments)。
 
- 无需实现固定接口(如
 
- JDK 动态代理: 
- 性能对比: - JDK 代理:便捷但受限(仅支持接口)。
- CGLIB:功能强大但发展缓慢,部分场景性能优于 JDK 代理。
- ByteBuddy:动态性更强,适合复杂场景。
 
二、Spring AOP 核心概念
1. 基本原理
- 基于动态代理实现(默认使用 JDK 代理,可配置为 CGLIB)。
- 关键术语: - 连接点(Join Point):程序执行中的具体点(如方法调用)。
- 切入点(Pointcut):通过表达式(如execution)定义匹配的连接点集合。- 示例:@Pointcut("execution(* org.derek.controller.*.*(..))")匹配指定包下的所有方法。
 
- 示例:
- 通知(Advice):在切入点处执行的增强逻辑,类型包括: - @Before(前置通知)、- @After(后置通知,无论是否异常)、- @AfterReturning(正常返回后)、- @AfterThrowing(异常抛出时)、- @Around(环绕通知)。
 
 
2. 常用注解与配置
- 启用 AOP 需引入依赖:spring-boot-starter-aop。
- 通过注解定义切面(@Aspect)、通知类型及切入点表达式。
三、@Transactional 注解详解
1. 实现原理
- 基于 Spring AOP 机制,通过代理拦截方法,在方法执行前后添加事务管理逻辑(开启、提交、回滚)。
- 默认使用Spring AOP(mode=Proxy,proxyTargetClass=false),即 JDK 代理(需接口),可配置为 CGLIB 代理(proxyTargetClass=true)。
2. 功能与作用
- 声明事务边界: - 开启事务:方法执行前创建新事务或加入现有事务。
- 提交事务:方法正常执行完成后提交。
- 回滚事务:方法抛出异常时根据配置回滚(默认仅回滚RuntimeException及其子类)。
 
- 使用场景:主要用于服务层(@Service)方法,实现数据库操作的原子性。
3. 异常不回滚常见原因
- 未抛出受检异常(Checked Exception),需显式配置@Transactional(rollbackFor = Exception.class)。
- 异常被内部捕获且未重新抛出。
- 方法非 public(Spring 默认仅拦截 public 方法)。
- 代理对象调用失效(如同一类内方法调用,未通过代理对象触发)。
- 事务传播机制配置不当(如Propagation.NOT_SUPPORTED不支持事务)。
四、知识关联与扩展
- 代理与 AOP 的关系:Spring AOP 通过动态代理实现,代理是 AOP 的底层技术支撑。
- 事务管理与 AOP 的结合:@Transactional本质是 AOP 切面,通过拦截方法实现声明式事务控制。
- 动态代理选型建议: - 有接口时优先使用 JDK 代理。
- 无接口时使用 CGLIB 或 ByteBuddy。
- 复杂场景(如字节码操作)可考虑 ByteBuddy。
 
通过以上知识点,可系统理解 Java 代理机制、Spring AOP 的核心原理及事务管理的实际应用,帮助排查开发中常见的事务不回滚等问题。
